Typescript: Mapped type optional -> required property issue

Created on 30 Dec 2016  路  4Comments  路  Source: microsoft/TypeScript

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

Working as Intended

Most helpful comment

It would also be good to extend the docs to explain how to use the Pick and Record types.

All 4 comments

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

manekinekko picture manekinekko  路  3Comments

remojansen picture remojansen  路  3Comments

siddjain picture siddjain  路  3Comments

Antony-Jones picture Antony-Jones  路  3Comments

jbondc picture jbondc  路  3Comments