diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2ccb41ae04218..d7d5e3d1c4dcc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6629,9 +6629,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return typeToTypeNodeHelper(type, context); } + function isMappedTypeHomomorphic(type: MappedType) { + return !!getHomomorphicTypeVariable(type); + } + function isHomomorphicMappedTypeWithNonHomomorphicInstantiation(type: MappedType) { - return isMappedTypeWithKeyofConstraintDeclaration(type) - && !(getModifiersTypeFromMappedType(type).flags & TypeFlags.TypeParameter); + return !!type.target && isMappedTypeHomomorphic(type.target as MappedType) && !isMappedTypeHomomorphic(type); } function createMappedTypeNodeFromType(type: MappedType) { diff --git a/tests/baselines/reference/mappedTypeGenericInstantiationPreservesInlineForm.js b/tests/baselines/reference/mappedTypeGenericInstantiationPreservesInlineForm.js new file mode 100644 index 0000000000000..3d049a82ae68e --- /dev/null +++ b/tests/baselines/reference/mappedTypeGenericInstantiationPreservesInlineForm.js @@ -0,0 +1,19 @@ +//// [mappedTypeGenericInstantiationPreservesInlineForm.ts] +// repro from #53109 + +export const test1 = >(schema: { + [K in keyof Required]: T[K]; +}) => {} + +export function test2>(schema: { + [K in keyof Required]: T[K]; +}) {}; + + + + +//// [mappedTypeGenericInstantiationPreservesInlineForm.d.ts] +export declare const test1: >(schema: { [K in keyof Required]: T[K]; }) => void; +export declare function test2>(schema: { + [K in keyof Required]: T[K]; +}): void; diff --git a/tests/baselines/reference/mappedTypeGenericInstantiationPreservesInlineForm.symbols b/tests/baselines/reference/mappedTypeGenericInstantiationPreservesInlineForm.symbols new file mode 100644 index 0000000000000..a550d839ddf4c --- /dev/null +++ b/tests/baselines/reference/mappedTypeGenericInstantiationPreservesInlineForm.symbols @@ -0,0 +1,33 @@ +=== tests/cases/compiler/mappedTypeGenericInstantiationPreservesInlineForm.ts === +// repro from #53109 + +export const test1 = >(schema: { +>test1 : Symbol(test1, Decl(mappedTypeGenericInstantiationPreservesInlineForm.ts, 2, 12)) +>T : Symbol(T, Decl(mappedTypeGenericInstantiationPreservesInlineForm.ts, 2, 22)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>schema : Symbol(schema, Decl(mappedTypeGenericInstantiationPreservesInlineForm.ts, 2, 49)) + + [K in keyof Required]: T[K]; +>K : Symbol(K, Decl(mappedTypeGenericInstantiationPreservesInlineForm.ts, 3, 5)) +>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypeGenericInstantiationPreservesInlineForm.ts, 2, 22)) +>T : Symbol(T, Decl(mappedTypeGenericInstantiationPreservesInlineForm.ts, 2, 22)) +>K : Symbol(K, Decl(mappedTypeGenericInstantiationPreservesInlineForm.ts, 3, 5)) + +}) => {} + +export function test2>(schema: { +>test2 : Symbol(test2, Decl(mappedTypeGenericInstantiationPreservesInlineForm.ts, 4, 8)) +>T : Symbol(T, Decl(mappedTypeGenericInstantiationPreservesInlineForm.ts, 6, 22)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>schema : Symbol(schema, Decl(mappedTypeGenericInstantiationPreservesInlineForm.ts, 6, 49)) + + [K in keyof Required]: T[K]; +>K : Symbol(K, Decl(mappedTypeGenericInstantiationPreservesInlineForm.ts, 7, 5)) +>Required : Symbol(Required, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypeGenericInstantiationPreservesInlineForm.ts, 6, 22)) +>T : Symbol(T, Decl(mappedTypeGenericInstantiationPreservesInlineForm.ts, 6, 22)) +>K : Symbol(K, Decl(mappedTypeGenericInstantiationPreservesInlineForm.ts, 7, 5)) + +}) {}; + diff --git a/tests/baselines/reference/mappedTypeGenericInstantiationPreservesInlineForm.types b/tests/baselines/reference/mappedTypeGenericInstantiationPreservesInlineForm.types new file mode 100644 index 0000000000000..60581c37ebdce --- /dev/null +++ b/tests/baselines/reference/mappedTypeGenericInstantiationPreservesInlineForm.types @@ -0,0 +1,18 @@ +=== tests/cases/compiler/mappedTypeGenericInstantiationPreservesInlineForm.ts === +// repro from #53109 + +export const test1 = >(schema: { +>test1 : >(schema: { [K in keyof Required]: T[K]; }) => void +>>(schema: { [K in keyof Required]: T[K];}) => {} : >(schema: { [K in keyof Required]: T[K]; }) => void +>schema : { [K in keyof Required]: T[K]; } + + [K in keyof Required]: T[K]; +}) => {} + +export function test2>(schema: { +>test2 : >(schema: { [K in keyof Required]: T[K]; }) => void +>schema : { [K in keyof Required]: T[K]; } + + [K in keyof Required]: T[K]; +}) {}; + diff --git a/tests/baselines/reference/mappedTypeUnionConstraintInferences.js b/tests/baselines/reference/mappedTypeUnionConstraintInferences.js index 7d1602718c18b..7d9e714d339bc 100644 --- a/tests/baselines/reference/mappedTypeUnionConstraintInferences.js +++ b/tests/baselines/reference/mappedTypeUnionConstraintInferences.js @@ -38,7 +38,7 @@ export declare type Omit = Pick>; export declare type PartialProperties = Partial> & Omit; export declare function doSomething_Actual(a: T): PartialProperties extends infer T_1 ? { [P in keyof T_1]: PartialProperties[P]; } : never; +}>(a: T): { [P in keyof PartialProperties]: PartialProperties[P]; }; export declare function doSomething_Expected(a: T): { diff --git a/tests/cases/compiler/mappedTypeGenericInstantiationPreservesInlineForm.ts b/tests/cases/compiler/mappedTypeGenericInstantiationPreservesInlineForm.ts new file mode 100644 index 0000000000000..cae88c35591d6 --- /dev/null +++ b/tests/cases/compiler/mappedTypeGenericInstantiationPreservesInlineForm.ts @@ -0,0 +1,13 @@ +// @strict: true +// @declaration: true +// @emitDeclarationOnly: true + +// repro from #53109 + +export const test1 = >(schema: { + [K in keyof Required]: T[K]; +}) => {} + +export function test2>(schema: { + [K in keyof Required]: T[K]; +}) {};