diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4d4f1bf69a808..b89d2679ee619 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -19103,9 +19103,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const mapper = createTypeMapper([getTypeParameterFromMappedType(objectType)], [index]); const templateMapper = combineTypeMappers(objectType.mapper, mapper); const instantiatedTemplateType = instantiateType(getTemplateTypeFromMappedType(objectType.target as MappedType || objectType), templateMapper); - const isOptional = getMappedTypeOptionality(objectType) > 0 || (isGenericType(objectType) ? - getCombinedMappedTypeOptionality(getModifiersTypeFromMappedType(objectType)) > 0 : - couldAccessOptionalProperty(objectType, index)); + const isOptional = isGenericType(objectType) ? + getCombinedMappedTypeOptionality(objectType) > 0 : + getMappedTypeOptionality(objectType) > 0 || couldAccessOptionalProperty(objectType, index); return addOptionality(instantiatedTemplateType, /*isProperty*/ true, isOptional); } diff --git a/tests/baselines/reference/genericMappedTypeOptionalityModifier1.errors.txt b/tests/baselines/reference/genericMappedTypeOptionalityModifier1.errors.txt new file mode 100644 index 0000000000000..ae2828fffda00 --- /dev/null +++ b/tests/baselines/reference/genericMappedTypeOptionalityModifier1.errors.txt @@ -0,0 +1,20 @@ +genericMappedTypeOptionalityModifier1.ts(10,9): error TS2322: Type 'undefined' is not assignable to type 'RequiredValues'. + + +==== genericMappedTypeOptionalityModifier1.ts (1 errors) ==== + // https://github.com/microsoft/TypeScript/issues/59902 + + const example = () => { + type SomeOptional = { [key in T]?: 1 }; + + type AllRequired = { [key in keyof SomeOptional]-?: 1 }; + + type RequiredValues = AllRequired[keyof AllRequired]; + + const x: RequiredValues = undefined; // error + ~ +!!! error TS2322: Type 'undefined' is not assignable to type 'RequiredValues'. + + return x; + }; + \ No newline at end of file diff --git a/tests/baselines/reference/genericMappedTypeOptionalityModifier1.symbols b/tests/baselines/reference/genericMappedTypeOptionalityModifier1.symbols new file mode 100644 index 0000000000000..a85768348f070 --- /dev/null +++ b/tests/baselines/reference/genericMappedTypeOptionalityModifier1.symbols @@ -0,0 +1,34 @@ +//// [tests/cases/compiler/genericMappedTypeOptionalityModifier1.ts] //// + +=== genericMappedTypeOptionalityModifier1.ts === +// https://github.com/microsoft/TypeScript/issues/59902 + +const example = () => { +>example : Symbol(example, Decl(genericMappedTypeOptionalityModifier1.ts, 2, 5)) +>T : Symbol(T, Decl(genericMappedTypeOptionalityModifier1.ts, 2, 17)) + + type SomeOptional = { [key in T]?: 1 }; +>SomeOptional : Symbol(SomeOptional, Decl(genericMappedTypeOptionalityModifier1.ts, 2, 41)) +>key : Symbol(key, Decl(genericMappedTypeOptionalityModifier1.ts, 3, 25)) +>T : Symbol(T, Decl(genericMappedTypeOptionalityModifier1.ts, 2, 17)) + + type AllRequired = { [key in keyof SomeOptional]-?: 1 }; +>AllRequired : Symbol(AllRequired, Decl(genericMappedTypeOptionalityModifier1.ts, 3, 41)) +>key : Symbol(key, Decl(genericMappedTypeOptionalityModifier1.ts, 5, 24)) +>SomeOptional : Symbol(SomeOptional, Decl(genericMappedTypeOptionalityModifier1.ts, 2, 41)) + + type RequiredValues = AllRequired[keyof AllRequired]; +>RequiredValues : Symbol(RequiredValues, Decl(genericMappedTypeOptionalityModifier1.ts, 5, 58)) +>AllRequired : Symbol(AllRequired, Decl(genericMappedTypeOptionalityModifier1.ts, 3, 41)) +>AllRequired : Symbol(AllRequired, Decl(genericMappedTypeOptionalityModifier1.ts, 3, 41)) + + const x: RequiredValues = undefined; // error +>x : Symbol(x, Decl(genericMappedTypeOptionalityModifier1.ts, 9, 7)) +>RequiredValues : Symbol(RequiredValues, Decl(genericMappedTypeOptionalityModifier1.ts, 5, 58)) +>undefined : Symbol(undefined) + + return x; +>x : Symbol(x, Decl(genericMappedTypeOptionalityModifier1.ts, 9, 7)) + +}; + diff --git a/tests/baselines/reference/genericMappedTypeOptionalityModifier1.types b/tests/baselines/reference/genericMappedTypeOptionalityModifier1.types new file mode 100644 index 0000000000000..5fda3e59615a9 --- /dev/null +++ b/tests/baselines/reference/genericMappedTypeOptionalityModifier1.types @@ -0,0 +1,35 @@ +//// [tests/cases/compiler/genericMappedTypeOptionalityModifier1.ts] //// + +=== genericMappedTypeOptionalityModifier1.ts === +// https://github.com/microsoft/TypeScript/issues/59902 + +const example = () => { +>example : () => { [key_1 in keyof { [key in T]?: 1 | undefined; }]-?: 1; }[T] +> : ^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>() => { type SomeOptional = { [key in T]?: 1 }; type AllRequired = { [key in keyof SomeOptional]-?: 1 }; type RequiredValues = AllRequired[keyof AllRequired]; const x: RequiredValues = undefined; // error return x;} : () => { [key_1 in keyof { [key in T]?: 1 | undefined; }]-?: 1; }[T] +> : ^ ^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + type SomeOptional = { [key in T]?: 1 }; +>SomeOptional : { [key in T]?: 1 | undefined; } +> : ^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ + + type AllRequired = { [key in keyof SomeOptional]-?: 1 }; +>AllRequired : { [key_1 in keyof { [key in T]?: 1 | undefined; }]-?: 1; } +> : ^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + type RequiredValues = AllRequired[keyof AllRequired]; +>RequiredValues : { [key_1 in keyof { [key in T]?: 1 | undefined; }]-?: 1; }[T] +> : ^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + const x: RequiredValues = undefined; // error +>x : { [key_1 in keyof { [key in T]?: 1 | undefined; }]-?: 1; }[T] +> : ^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>undefined : undefined +> : ^^^^^^^^^ + + return x; +>x : { [key_1 in keyof { [key in T]?: 1 | undefined; }]-?: 1; }[T] +> : ^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +}; + diff --git a/tests/cases/compiler/genericMappedTypeOptionalityModifier1.ts b/tests/cases/compiler/genericMappedTypeOptionalityModifier1.ts new file mode 100644 index 0000000000000..cba5520e4c5e4 --- /dev/null +++ b/tests/cases/compiler/genericMappedTypeOptionalityModifier1.ts @@ -0,0 +1,16 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/59902 + +const example = () => { + type SomeOptional = { [key in T]?: 1 }; + + type AllRequired = { [key in keyof SomeOptional]-?: 1 }; + + type RequiredValues = AllRequired[keyof AllRequired]; + + const x: RequiredValues = undefined; // error + + return x; +};