Microsoft/TypeScript

Type mapping unexpectedly leads to missing keys

Open

#48,069 opened on 2022幎3月1日

GitHub で芋る
 (10 comments) (0 reactions) (0 assignees)TypeScript (6,726 forks)batch import
BugDomain: Mapped TypesHelp Wanted

Repository metrics

Stars
 (48,455 stars)
PR merge metrics
 (平均マヌゞ 6d 17h) (30d で 9 merged PRs)

説明

Bug Report

🔎 Search Terms

mapped types missing keys

🕗 Version & Regression Information

  • I was unable to test this on prior versions because we didn't use the --exactOptionalPropertyTypes previously

⏯ Playground Link

Playground link with relevant code

💻 Code

type Flatten<T> = { [K in keyof T]: T[K] };

type OptionalKeys<T> = { [K in keyof T]: {} extends Pick<T, K> ? K : never }[keyof T];
type OptionalProperties<T> = Pick<T, OptionalKeys<T>>;

type UndefinedPropertyKeys<T> = { [K in keyof T]: undefined extends T[K] ? K : never }[keyof T];
type DefinedPropertyKeys<T> = { [K in keyof T]: undefined extends T[K] ? never : K }[keyof T];

type UndefinedToOptional<T> = Flatten<{
    [K in UndefinedPropertyKeys<T>]+?: T[K]
} & {
    [K in DefinedPropertyKeys<T>]: T[K]
}>;

type Convert<T> = Flatten<{ [K in keyof OptionalProperties<T>]-?: T[K] }>;

type input = {
    remove: number | undefined;
    makeMandatory?: number;
    retain?: number | undefined;
}

//Equals Convert<input>
type intermediateInput = {
    makeMandatory: number;
    retain: number | undefined;
}

//Type is { makeMandatory: number; retain?: number | undefined }
const x: UndefinedToOptional<intermediateInput> = {
    makeMandatory: 0,
};

//Type is { }
const y: UndefinedToOptional<Convert<input>> = {
    makeMandatory: 0,
};

🙁 Actual behavior

The keys of the mapped type are stripped when applying another type mapping.

🙂 Expected behavior

The result of mapping a mapped type should show the same behaviour as mapping a recreation of the mapped type.

コントリビュヌタヌガむド