TS dev here. Mat, you're by far the best resource for TS magic on the net. Thank you!
The reason Prettify works is internal compiler logic and not documented. There are of course two things to understand: the first is why Prettify<T> is equivalent to T, which should be obvious enough. The more complicated thing is why does the Typescript compiler simplify the type for you? TypeScript typically uses lazy type evaluation, meaning it keeps the crazy nested structure of your types until it has to evaluate a value against them. It has certain heuristics to simplify computation, where it will sometimes evaluate things eagerly to save it work later. One of those heuristics is specifically when you construct a new explicit mapped type with a constraint, it will attempt to evaluate that in-place to resolve the constraint eagerly. The `& {}` is doing the work as the constraint here. Of course, if the compiler were a bit smarter and were coded differently, it might have decided instead to recognize `& {}` as a no-op constraint and just drop it, and then leave the mapped type without eagerly evaluating. Which is why this is very much compiler-implementation-dependent behavior and not documented, and could easily break in later versions (although people use it so much, they may get some push-back if they break it).
I'd ask MS to add Prettify generic into the core. I tired to add it in-place here and there, across the projects. A separate "thank you" to you, Matt, for it.
The loose autocomplete is something I was looking for but didn't know it existed. Your timing with this video is spot on!
Just a note on the Prettify<T> type; it does come with overhead, especially on large types–i.e. if you are intersecting many types together. Effectively it creates a completely new type, instead of referencing existing types. Use with caution!
The loose autocomplete is something I've wondered was possible for a long time, thanks!
type Prettify<T> = {[K in keyof T] : T[K]} type LooseAutocomplete<T extends string> = T | Omit<string , T>
the loose autocomplete and IIMT save my life. Matt you're a Warlock!!
A quick improvement for the mapped types - it can even be generic: type Setters<T extends object> = { [K in Extract<keyof T, string> as `set${Capitalize<K>}`]?: (value: T[K]) => T[K] }; This will create an object with setter functions for any object type. Great video! Mapped types are definitely something we should all think about more often. So powerful
I purchased your course and life just happened to make me move on from Typescript due to my working and personal projects' requirements, and I never had the time to watch it through. Nevertheless, I don't regret having bought it because of how passionate you are about this stuff. Hopefully one day I'm going to watch it all and apply its knowledge!
mapped types actually blew my mind, i never used it this way
Something I like to use in a few of my utility types is the fact you can use logic inside the type. One of my favorite types is a type that replaces all instances of one type with another.
Thanks for this video! We really need the Loose autocomplete with Zod as well!
no one comes close when it comes to typescript education. You're the goat Matt! ❤
Regarding the "& {}" trick: it's actually a performance improvement that the editor does not show you the "pretty" type, but just the "alias" of the type. By using "& {}" we basically force the editor (or the language server) to evaluate the new type. Note that I got that information from Gemini when I needed to "resolve" a type in a lib I'm writing as well. But the information does make sense to me, so I take it as valid.
A nice trick I learnt recently is template literal types with enums ``` enum MyEnum { FIRST = "FIRST", SECOND = "SECOND", } type EnumAndString = MyEnum | `${MyEnum}`; ``` Now you can use either MyEnum or the enum values "FIRST" | "SECOND"
Love the loose autocomplete! Just added it to a project. 💚
Prefer { traceId?: string | undefined } over { traceId?: string }. It's important if you set exactOptionalPropertyTypes on, which I recommend to do if you can. Prettify can be dangerous as it ruins internal logic of the type it is applied to. If there was some kind on union, it's broken. It would be nice to hear more about differenses between Extract<X, Y> and X & Y. There definitely are.
03:13 `pick` and `omit` are among the most dangerous and hazardous utilities in TypeScript, at least within the VSCode IDE. There is no native mechanism to track and verify that you are referencing properties from another object. My solution is to create a separate interface and explicitly reference it, for example: { key1: InterfaceA['key1'] } If you delete or modify a key using F2, this will cause errors to propagate throughout your project. Good luck if you're working with hundreds of files. Never use omit or pick if your IDE dont support refs.
@feldinho