6 ms·
Utility Types[0] will help you get to the next level on Typescript. It's important to know them and know how and when to use them. [0] https://www.typescriptla
by skywal_l 5y ago
Utility Types[0] will help you get to the next level on Typescript. It's important to know them and know how and when to use them.
[0] https://www.typescriptlang.org/docs/handbook/utility-types.html https://www.typescriptlang.org/docs/handbook/utility-types.h...
- mithusingh32 5y agoWow, thanks for this. I wasn't even aware of these. I'm surprised I rarely see these in courses/tutorial. These should be like day 1 material.
- shadowgovt 5y agoTS has been around long enough that it suffers from the 'obsolete tutorial' problem (one I first observed learning C++): many of the utility types didn't exist when many of the popular tutorials were first written.
- skywal_l 5y agoTypescript 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, K extends keyof T> = T & { [U in keyof Pick<T, K>]-?: T[U] }; class A { foo?: number; bar?: number; baz?: number; } type MandatoryFields = "foo" | "baz"; type B = Ensure<A, MandatoryFields>; const b: B = { foo: 42 }; Here, ts will complain that b is missing baz.
- CuriouslyC 5y agoWhy 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.
- goto11 5y agoUtility types are useful for example in the React API. You have a "state" defined as a set of properties. Then you have a setState() method where you return the set of properties you want to update, which may be a subset of the full state. So if the type of the component state is TState, then the return type of setState() can be defined as Partial<TState>.
- phailhaus 5y agoA better example is `Partial`, which makes all properties on an interface optional. Lots of use cases for that, like creating a `Dictionary` type that forces you to check for undefined values, or allowing you to support partial-updates to types without having to repeat your interfaces. The other thing is that types are more often used than read. You don't need to read the `MandatoryFields` type definition often, because your IDE/typechecker will automatically enforce the contract and tell you when you're missing properties.
- srcreigh 5y agoTIL, interfaces can extend classes in TypeScript. [0] If interfaces could not extend classes, that would be a reason to use type programming. Another reason could be a generic interface. If you have a lifecycle where a type is mutable at one point but immutable at later points, you could use mapped types to enforce those constraints on the class methods generically. [0]: https://www.typescriptlang.org/play?#code/MYGwhgzhAEAKCmAnCB7AdtA3gKGn6aYAtvAFzQQAuiAlmgOYDcu+w6ViArsJSogBSES5DnXoBKLC3z5KACxoQAdEPjQAvAWLxmMgL7YD2OpSQAzMMDWwwieGkrR4AD1NoAJjATJ0UmcAUQdzs0cm9UNABtAF1mIzY0KgowEBAATzDbe0dNHH9A4PtySMxVcgByACkUeHK9aMMgA https://www.typescriptlang.org/play?#code/MYGwhgzhAEAKCmAnCB...
- nkingsy 5y agoI'm building a strongly typed form abstraction layer for work. I use code like this to express "if this generic can be undefined, this field is required. Otherwise it cannot be used". So: FormElement<string|undefined> needs to have a "disabled" function, indicating conditions under which it becomes disabled (and absent from the model), while FormElement<string> must not have a disabled function, as it will always be present in the model. One pitfall of this approach is it requires a lot of trial and error to find the incantation that both works and doesn't swallow error messages.
- yulaow 5y agoThis seems extremely hard to read for me, I would have an hard time trying to understand what it does if I found it in any source code
- skywal_l 5y agotype Ensure I define a type called Ensure <T, K extends keyof T> This type takes two type parameters, one called T and the other K which will consist of Keys belonging to the type T (in our case, "foo", "bar" or "baz"). = T & This new type (called Ensure) will be equal to the union of two types: One will be T and the other will be: { [U in keyof Pick<T, K>] A new type which keys will be picked among the key listed in K -? To which we will remove the potential optional qualifier : T[U] }; And which types will be the same as in T.
- alpha_squared 5y agoThis feels like considerable cognitive load for any developer that needs to work in more than one language.
- chana_masala 5y agoIsn't that the main challenge of being a programmer? Anyways I don't find it hard to read, but I write TS like that every day
- bcrosby95 5y agoProbably depends upon your job. The main challenge of being a programmer, in the sorts of projects I work on, is communication - with customers, management, and other developers.
- jorisd 5y agoMost of the implementation details here don't really matter until you need to modify these advanced types directly. That Ensure type definition line in that example is a low level detail that you put in a library somewhere, import throughout your codebase, and then mostly forget about. In practice you'd have someone that understands this set it up once, and then document its usage for others, maybe document the implementation to make it easier to modify later. The TS compiler is surprisingly good at giving you good readable error messages as well when your code violates these advanced types; the errors tell you what you specified and what is supported, it doesn't display the low level type logic as part of the error users see. This means that there's very little need for anyone to really how these type definitions work. EDIT: clarifications and spelling.
- ketzo 5y agoOk, the comments that this is a little hard to read are fair... but this is really cool. Thanks for sharing.
- dllthomas 5y agoI don't have it handy but with template literal types I was able to have a type of "stripped strings" (that is, strings without leading or trailing whitespace) that seemed surprisingly usable - string literals would match (or not, as appropriate) with no boilerplate, while dynamic strings would need to be fed to a cleaning function. I never put it in production, partially because of concerns over maintainability but far more because I had no need for it.
- flippinburgers 5y agoJust have a concrete type (class/interface) that specifies required fields. This is overkill that will only confuse everyone who isn't the original author.
- goto11 5y agoDepends on how much you can learn on one day I guess, but TypeScript have lots of features which should be learned before Utility types. For example type parameters, type unions, the role of null and undefined, type assertions etc.
- btown 5y agoI recently saw a code example in the VSCode repository where Extract was used in a really awesome way. Say you have a complex class with lots of fields and methods, and you want something that's a specifier for either a constructor's parameter or a query system. Often times, that will be very similar to the underlying class, but just the fields in it - excluding every member that's not a function. Instead of rewriting every single field name for your new type, just have your new type be Exclude<MyType, Function> or Partial<Exclude<MyType, Function>> and the resulting type is perfect for your needs. Pick is also really useful if you have an interface that passes down a subset of complex things you get from a library; no need to retype their types, just extend a Pick of the library type. In short, utility types are awesome!
- cuddlecake 5y agoFunnily enough, I have done a session today where I live-coded using the utility types in an effort to explain most of the types listed on that page to a few of my colleagues.
- ofrzeta 5y agoI really don't get the point of operations on types such as 'type TodoInfo = Omit<Todo, "completed" | "createdAt">'. Is this a real use case? Why not just literally write down the properties? Surely easier to read and in the end maybe even easier to maintain.
- scotty79 5y agoIt depends on what your anticipation of the future evolution of TodoInfo type is. If you think it will have more special fields like completed and createdAt that you don't want to pass on in most contexts, then it's better to list the fields that you want to pass on. But if you expect it to not have more of those and rather get (or loose) more fields that you want to pass on, then it's better to list the ones that you want to omit. Another trade-off might be that when the new field is added and you'll forget to update the other pieces of code, will it do less harm to pass the field you intended to omit, or to omit the field you intended to pass. Or which error will be easier for you to discover in your use case.
- nsonha 5y agoA higher order react component that consumes those props and swallows them before passing down to the target.
- Attained 5y agoRenaming attributes propogates through these types. It makes refactoring better.
- nsonha 5y agothe only complain have with these is that there is no namespace or anything that allows me to discover them. You have to follow all the release notes or check lib.d.ts. In comparison, flowtype prefixes them with $, so when I type "$", I get the suggestion.