镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Mapped type optional -> required property issue #13224

Description

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

Activity

  1. JakeGinnivan commented on Dec 30, 2016

    @JakeGinnivan
    Author

    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.

  2. mhegazy commented on Dec 30, 2016

    @mhegazy
    Contributor

    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.

  3. JakeGinnivan commented on Dec 31, 2016

    @JakeGinnivan
    Author

    Thanks, have opened a PR in the docs which adds some of this information. Appreciate the good explanation.

  4. JakeGinnivan commented on Dec 31, 2016

    @JakeGinnivan
    Author

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

  5. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions