TypeScript Version: 2.1.4
Code
https://github.com/JakeGinnivan/TypeScriptMappedTypeIssue
Expected behavior:
The mapped type
export type PropDescriptions<T> = {
[P in keyof T]: string
}
Is marking all the properties as required, I would expect this to fail:
interface ThingProps {
prop1: string
prop2?: string
}
const expected: PropDescriptions<ThingProps> = {
prop1: 'Ok'
}
with Property 'prop2' is missing in type {...}
Actual behavior:
No compilation error
As a side note, it would be awesome if you could iterate at runtime on the keys of an interface. I guess that starts moving into the reflection questions, but it would be super handy if code could be emitted based on type information. So not runtime reflection but static templating.
I probably need to generate the styleguide from the typescript source rather than the approach I am taking.
Mapped types that are a homomorphic transformation are treated specially in the type system. the above type PropDescriptions is one of such. The type system knows that PropDescriptions<T> is a transformation of T, and it copies the readonly and ? modifiers on the new type as it is generated from the source. Think of ReadOnly<T>, where T has optional properties, you would expect the result to have optional properties as well.
You however change the mapping to make it a non-homomorphic transformation as such:
type PropDescriptions<T, K extends string> = {
[P in K]: string
}
and you would instantiate it with:
const expected: PropDescriptions<ThingProps, keyof ThingProps> = ...
Notice the constraint on K is string; this way the type system can not assert that the result of this transformation is a homomorphic mapping on T, and thus no modifiers are copied through.
It is worth noting that if the constraint was K extends keyof T (e.g. the definition of type Pick in lib.d.ts`), the transformation would still be considered a homomorphic one.
Thanks, have opened a PR in the docs which adds some of this information. Appreciate the good explanation.
It would also be good to extend the docs to explain how to use the Pick and Record types.
Most helpful comment
It would also be good to extend the docs to explain how to use the
PickandRecordtypes.