Live data from Hacker News

Tricks I wish I knew when I learned TypeScript

cstrnt.dev

231–240 of 276 posts

Re: Tricks I wish I knew when I learned TypeScript

#231
post #122

I'm so happy powerful type systems are more popular now. TypeScript bringing a great type system to a language as popular as JS is fantastic. Rust is also a great way to get a great type system while staying in a systems programming and procedural environment. Hell, even python type annotations support union types. I never knew the depth of type systems until the last year when I took a type theory course and a compi…

What course?

Re: Tricks I wish I knew when I learned TypeScript

#232

Earlier quoted context omitted.

Me, reading the link at the top of this thread: oh wow, those are really cool. Me, reading this example: oh no, those all need to be added to our project's lint rules to make sure no-one uses them.

Why would you prevent their usage? They're incredibly helpful

I guess it'd be OK as long as everyone always accompanied such lines with a comment, with at least one line per symbol or character it's identifying & explaining. As all but the most trivial regexes warrant.

Re: Tricks I wish I knew when I learned TypeScript

#233

Earlier quoted context omitted.

Typescript is actually a great language. And with those utility types, you can do pretty fun stuff like, for example, you want to mutate a type so that some fields become mandatory: type Ensure = T & { [U in keyof Pick ]-?: T[U] }; class A { foo?: number; bar?: number; baz?: number; } type MandatoryFields = "foo" | "baz"; type B = Ensure ; const b: B = { foo: 42 }; Here, ts will complain that b is missing baz.

Why write code like that, instead of extending the class with a mandatory property? The above code is going to be inscrutable to a lot of engineers, and this isn't something like an ORM where there's a good reason for that.

The advantage here is that you are not repeating the type of the property twice (once as optional in the base type, once as mandatory in the extended class).

Even though the code may seem inscrutable, note that the resulting type is fairly easy to understand in your IDE. That is, if you hover over the "B" to see what the type definition is, you see:

  type B = A & {
    foo: number;
    baz: number;
  }
If you defined the type like this (which is equivalent to extending the class as you were proposing) and later on someone changes the type of one such mandatory properties in the base and/or extended class without changing the other, the error becomes much much weird, on the lines of:

> Type 'number' is not assignable to type 'never'.(2322)

Here typescript is saying that a prop cannot have a value (type never) because the base class defines it as "number?" but the extended one defines it as "string", and the intersection between them is empty. This is hard to understand when it pops out where you don't expect it. Harder than ignoring the weird "Ensure" thing, seeing what it does (the resulting type B definition) and moving on.

Defining advanced types may be cumbersome, but dealing with code that uses them is still approachable. This allows the more experienced team members to "shape the ground" and less experienced members still reap the benefits even if they don't fully understand how the thing works.

Re: Tricks I wish I knew when I learned TypeScript

#234

Earlier quoted context omitted.

The core problem here is that you don't actually want to check if something is an object, but whether it matches the Human type. The correct way to do that is to define a type guard [0], for example: function isHuman(input: any): input is Human { return ( Boolean(input) && Object.prototype.hasOwnProperty.call(input, "name") && Object.prototype.hasOwnProperty.call(input, "age") ); } There are libraries which can autom…

> There are libraries which can automate this for you which is the route I would recommend Which libraries do you recommend? I've had to do this a couple of times in my current project and it's painful (and I made mistakes).

Personally I really enjoy Typanion [0] since it's very similar to Yup [1] which I previously had extensive experience with. You can find more alternatives and a lengthy discussion about the whole problem space and its history in [2].

[0] https://github.com/arcanis/typanion

[1] https://github.com/jquense/yup

[2] https://github.com/microsoft/TypeScript/issues/3628

Re: Tricks I wish I knew when I learned TypeScript

#235

Earlier quoted context omitted.

> Everything that TS does JS libraries do better Which ones do you need to do everything TS does? > without the horrible tradeoffs Which tradeoffs are horrible?

Not OP but I do tend to avoid TS. I don't like the additional friction of working with the language (transpiling, unable to copy/paste directly into an interpreter). I also feel like the community at large writes awful baroque code that makes me want to die. Why use a function when 18 classes subclassing eachother across 4 files will do? If you're familiar with the tiktoker @khaby.lame, TS feels like exactly the over…

TS !== crazy OOP. For some reason, there are people who just want to use Java style OOP in TS. Nest.js is one library heavily promoting that. I can't digest such codebases, they are the definition of over-engineering to me. Fortunately, out of dozens of medium to big TS projects I worked on, only one used that style. In all the other projects there were very few if any classes.

Re: Tricks I wish I knew when I learned TypeScript

#236
post #117

Still working on this, but might give someone a laugh :) Problem 1 from Project Euler in TypeScripts Types https://github.com/iiTzEddyGG/typing-euler/blob/master/src/p...

I am highly interested in type programming lately, exactly the kind of thing you're doing here. Do you have any other resources that inspired you? Here are some of my favorites: https://gist.github.com/hediet/63f4844acf5ac330804801084f87a... https://github.com/codemix/ts-sql https://github.com/jamiebuilds/json-parser-in-typescript-ver... https://gist.github.com/acutmore/9d2ce837f019608f26ff54e0b1c...

I really like Type Driven Development in Idris but that's a little more serious (it's things you can do in production!). But my all time favourite writing ever is https://aphyr.com/posts/342-typing-the-technical-interview

Re: Tricks I wish I knew when I learned TypeScript

#237

Earlier quoted context omitted.

Why write code like that, instead of extending the class with a mandatory property? The above code is going to be inscrutable to a lot of engineers, and this isn't something like an ORM where there's a good reason for that.

The advantage here is that you are not repeating the type of the property twice (once as optional in the base type, once as mandatory in the extended class). Even though the code may seem inscrutable, note that the resulting type is fairly easy to understand in your IDE. That is, if you hover over the "B" to see what the type definition is, you see: type B = A & { foo: number; baz: number; } If you defined the type l…

The beginner programmer copies the property definition.

The advanced programmer simply writes "type Ensure = T & { [U in keyof Pick]-?: T[U] };", thus removing the need to copy the property.

The master programmer copies the property definition.

Re: Tricks I wish I knew when I learned TypeScript

#238

Does Typescript get better? I've been forced to use it for my most recent project, but haven't been given any time to read through the documentation. I've found that I'm spending about 99.9999% of my development time trying to figure out how to get my IDE to not show that their are typescript problem. At this point I hate typescript with the burning fury of a trillion suns. I wonder if this is everyone else's experie…

Typescript is very easy, super powerful and lovely. If you are having problems is because there is something you are still not getting, remember is just Javascript but with a super set of tools that make it beautiful

Re: Tricks I wish I knew when I learned TypeScript

#239
post #139

The third example describes something useful in record types, but goes about it in what seems an odd way, and ends up suboptimal as a result. I'd instead use an object type like this: type Human = { name: string; age: number; } which also enforces value types in the compiler, rather than requiring runtime guards.

The type itself is fine but how it is checked and used is not. The following would be better, and in this case you will also have a Human type inside the forEach callback: // ... other code type Human = { name: string; age: number } const isHuman = (obj: unknown): obj is Human => obj && typeof obj === 'object' && 'name' in obj && 'age' in obj; // you can complete the gaps here and also check the property types someAr…

The type guard may be useful when transferring that array server->client or vice versa, or for an array from any other untrusted source, but I don’t think that was the purpose of the demo in the article. When the array in question is coming from the same code base that kind of runtime type check is redundant.

Re: Tricks I wish I knew when I learned TypeScript

#240
post #18

I actually don't really like Record types in the way people/library maintainers often use them - the type-checker asserts that values are actually present for all the specified keys, which is fine if the objects with the Record type really were exhaustive; but instead I often see them used where the reality of the data is a Partial - some keys are missing. Something about the abstraction causes people to misuse it fr…

Yep, and in your own code you can tell TS to verify your property access with the setting `noPropertyAccessFromIndexSignature` ( https://devblogs.microsoft.com/typescript/announcing-typescr... ) The TS crew did discuss having a "pedantic" mode, which is stricter than "strict", but I don't think it's on the roadmap any more.

That one as well as the noUncheckedIndexedAccess ought to be defaults when in strict mode.
Post reply on HN