|
|
|
|
|
by kilburn
1708 days ago
|
|
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. |
|
The advanced programmer simply writes "type Ensure<T, K extends keyof T> = T & { [U in keyof Pick<T, K>]-?: T[U] };", thus removing the need to copy the property.
The master programmer copies the property definition.