diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c5ffd98f9ae..54339bbdf3f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10458,7 +10458,7 @@ namespace ts { existingProp.keyType = getUnionType([existingProp.keyType, keyType]); } else { - const modifiersProp = getPropertyOfType(modifiersType, propName); + const modifiersProp = isTypeUsableAsPropertyName(keyType) ? getPropertyOfType(modifiersType, getPropertyNameFromType(keyType)) : undefined; const isOptional = !!(templateModifiers & MappedTypeModifiers.IncludeOptional || !(templateModifiers & MappedTypeModifiers.ExcludeOptional) && modifiersProp && modifiersProp.flags & SymbolFlags.Optional); const isReadonly = !!(templateModifiers & MappedTypeModifiers.IncludeReadonly || diff --git a/tests/baselines/reference/mappedTypeAsClauses.js b/tests/baselines/reference/mappedTypeAsClauses.js index 75c1d32cd60..9bb361db932 100644 --- a/tests/baselines/reference/mappedTypeAsClauses.js +++ b/tests/baselines/reference/mappedTypeAsClauses.js @@ -28,6 +28,20 @@ type DoubleProp = { [P in keyof T & string as `${P}1` | `${P}2`]: T[P] } type TD1 = DoubleProp<{ a: string, b: number }>; // { a1: string, a2: string, b1: number, b2: number } type TD2 = keyof TD1; // 'a1' | 'a2' | 'b1' | 'b2' type TD3 = keyof DoubleProp; // `${keyof U & string}1` | `${keyof U & string}2` + +// Repro from #40619 + +type Lazyify = { + [K in keyof T as `get${capitalize string & K}`]: () => T[K] +}; + +interface Person { + readonly name: string; + age: number; + location?: string; +} + +type LazyPerson = Lazyify; //// [mappedTypeAsClauses.js] @@ -82,3 +96,12 @@ declare type TD1 = DoubleProp<{ }>; declare type TD2 = keyof TD1; declare type TD3 = keyof DoubleProp; +declare type Lazyify = { + [K in keyof T as `get${capitalize string & K}`]: () => T[K]; +}; +interface Person { + readonly name: string; + age: number; + location?: string; +} +declare type LazyPerson = Lazyify; diff --git a/tests/baselines/reference/mappedTypeAsClauses.symbols b/tests/baselines/reference/mappedTypeAsClauses.symbols index 75768ce31af..31a9ca0bef8 100644 --- a/tests/baselines/reference/mappedTypeAsClauses.symbols +++ b/tests/baselines/reference/mappedTypeAsClauses.symbols @@ -108,3 +108,36 @@ type TD3 = keyof DoubleProp; // `${keyof U & string}1` | `${keyof U & str >DoubleProp : Symbol(DoubleProp, Decl(mappedTypeAsClauses.ts, 21, 85)) >U : Symbol(U, Decl(mappedTypeAsClauses.ts, 28, 9)) +// Repro from #40619 + +type Lazyify = { +>Lazyify : Symbol(Lazyify, Decl(mappedTypeAsClauses.ts, 28, 34)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 32, 13)) + + [K in keyof T as `get${capitalize string & K}`]: () => T[K] +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 33, 5)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 32, 13)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 33, 5)) +>T : Symbol(T, Decl(mappedTypeAsClauses.ts, 32, 13)) +>K : Symbol(K, Decl(mappedTypeAsClauses.ts, 33, 5)) + +}; + +interface Person { +>Person : Symbol(Person, Decl(mappedTypeAsClauses.ts, 34, 2)) + + readonly name: string; +>name : Symbol(Person.name, Decl(mappedTypeAsClauses.ts, 36, 18)) + + age: number; +>age : Symbol(Person.age, Decl(mappedTypeAsClauses.ts, 37, 26)) + + location?: string; +>location : Symbol(Person.location, Decl(mappedTypeAsClauses.ts, 38, 16)) +} + +type LazyPerson = Lazyify; +>LazyPerson : Symbol(LazyPerson, Decl(mappedTypeAsClauses.ts, 40, 1)) +>Lazyify : Symbol(Lazyify, Decl(mappedTypeAsClauses.ts, 28, 34)) +>Person : Symbol(Person, Decl(mappedTypeAsClauses.ts, 34, 2)) + diff --git a/tests/baselines/reference/mappedTypeAsClauses.types b/tests/baselines/reference/mappedTypeAsClauses.types index 438d9c1fcbf..f2426a9c74c 100644 --- a/tests/baselines/reference/mappedTypeAsClauses.types +++ b/tests/baselines/reference/mappedTypeAsClauses.types @@ -66,3 +66,25 @@ type TD2 = keyof TD1; // 'a1' | 'a2' | 'b1' | 'b2' type TD3 = keyof DoubleProp; // `${keyof U & string}1` | `${keyof U & string}2` >TD3 : `${keyof U & string}1` | `${keyof U & string}2` +// Repro from #40619 + +type Lazyify = { +>Lazyify : Lazyify + + [K in keyof T as `get${capitalize string & K}`]: () => T[K] +}; + +interface Person { + readonly name: string; +>name : string + + age: number; +>age : number + + location?: string; +>location : string | undefined +} + +type LazyPerson = Lazyify; +>LazyPerson : Lazyify + diff --git a/tests/cases/conformance/types/mapped/mappedTypeAsClauses.ts b/tests/cases/conformance/types/mapped/mappedTypeAsClauses.ts index 51f6bd720bf..542503e82dc 100644 --- a/tests/cases/conformance/types/mapped/mappedTypeAsClauses.ts +++ b/tests/cases/conformance/types/mapped/mappedTypeAsClauses.ts @@ -30,3 +30,17 @@ type DoubleProp = { [P in keyof T & string as `${P}1` | `${P}2`]: T[P] } type TD1 = DoubleProp<{ a: string, b: number }>; // { a1: string, a2: string, b1: number, b2: number } type TD2 = keyof TD1; // 'a1' | 'a2' | 'b1' | 'b2' type TD3 = keyof DoubleProp; // `${keyof U & string}1` | `${keyof U & string}2` + +// Repro from #40619 + +type Lazyify = { + [K in keyof T as `get${capitalize string & K}`]: () => T[K] +}; + +interface Person { + readonly name: string; + age: number; + location?: string; +} + +type LazyPerson = Lazyify;