by wazbug on 3/24/24, 3:02 PM with 78 comments
by jitl on 3/24/24, 5:59 PM
They’re great in small doses where you really need them, but overuse or widespread use of complex types will make your build slower. It’s much better to avoid generics or mapped types if you can. The typings for a tagged template literal (without digit format specifiers like %d4) don’t require any generics.
I love to write code like this, but I’m guilty of over using fancy types and I flinch when I see a typescript build profile showing 45s+ spent on generic types I wrote without realizing the cost.
by eyelidlessness on 3/24/24, 5:50 PM
Which is to say, these names almost always make types like this more clear:
- Head: the first item in the input type you’re iterating through
- Tail: the remaining items or unprocessed structure you’ll likely recurse on next
- Acc (or pick your favorite “reduced” idiom): a named type for the intermediate product which will become the final type when you finish iterating. This can be provided as an optional parameter with an empty tuple as its default, largely modeling a typical reduce (apart from inverting the common parameter order).
It also helps, IME, to put a “base case” first in the type’s conditions.
When all of these names and patterns are utilized, the resulting type tends to look quite a lot like an equivalent runtime function you could encounter for producing the value equivalent to its type. This is great because you can even write the runtime function to match the type’s logic. This demonstrates both what the type is doing for people who find these “complex types” intimidating, and that the type accurately describes the value it’s associated with.
by IceDane on 3/24/24, 3:56 PM
There is a way to make this easier to extend, though: https://tsplay.dev/WGbEXm
Can't tell off the top of my head if there are any disadvantages to this approach though.
by crgwbr on 3/24/24, 9:28 PM
https://www.hacklewayne.com/a-truly-strongly-typed-printf-in...
by pkkm on 3/24/24, 4:35 PM
Recently though, I've been wondering whether advanced type system stuff is the right approach. It usually becomes pretty complicated, like another language on top of the regular language. Maybe it would be easier to have some kind of framework for compiler plugins that do extra checks. Something that would make it easy to check format strings or enforce rules on custom attributes, like Linux's sparse does, using plain imperative code that's readable to the average dev. Large projects would have an extra directory for compile time checks in addition to the tests directory they have now.
But I haven't seen any language community do something like that. What am I missing?
by yen223 on 3/25/24, 3:49 AM
This is something that most mainstream language's type system cannot do.
(This may be obvious, but a lot of commenters here might have missed that.)
by ruined on 3/24/24, 4:40 PM
you can also use typescript-eslint/restrict-template-expressions if you find yourself running into problems with that
https://typescript-eslint.io/rules/restrict-template-express...
by taeric on 3/24/24, 5:40 PM
by akira2501 on 3/24/24, 6:41 PM
by k__ on 3/24/24, 5:11 PM
Now do ReScript. :D
by beders on 3/24/24, 8:08 PM
Please don't adopt this.
by Touche on 3/24/24, 4:03 PM