Properly preserve modifiers in homomorphic mapped types with 'as' clauses (#40633)

* Use original property name to fetch source property for modifiers

* Add regression test

* Accept new baselines
This commit is contained in:
Anders Hejlsberg
2020-09-19 06:12:39 -10:00
committed by GitHub
parent 8cdf5a20d9
commit 17c7c261d4
5 changed files with 93 additions and 1 deletions
+1 -1
View File
@@ -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 ||
@@ -28,6 +28,20 @@ type DoubleProp<T> = { [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<U> = keyof DoubleProp<U>; // `${keyof U & string}1` | `${keyof U & string}2`
// Repro from #40619
type Lazyify<T> = {
[K in keyof T as `get${capitalize string & K}`]: () => T[K]
};
interface Person {
readonly name: string;
age: number;
location?: string;
}
type LazyPerson = Lazyify<Person>;
//// [mappedTypeAsClauses.js]
@@ -82,3 +96,12 @@ declare type TD1 = DoubleProp<{
}>;
declare type TD2 = keyof TD1;
declare type TD3<U> = keyof DoubleProp<U>;
declare type Lazyify<T> = {
[K in keyof T as `get${capitalize string & K}`]: () => T[K];
};
interface Person {
readonly name: string;
age: number;
location?: string;
}
declare type LazyPerson = Lazyify<Person>;
@@ -108,3 +108,36 @@ type TD3<U> = keyof DoubleProp<U>; // `${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<T> = {
>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<Person>;
>LazyPerson : Symbol(LazyPerson, Decl(mappedTypeAsClauses.ts, 40, 1))
>Lazyify : Symbol(Lazyify, Decl(mappedTypeAsClauses.ts, 28, 34))
>Person : Symbol(Person, Decl(mappedTypeAsClauses.ts, 34, 2))
@@ -66,3 +66,25 @@ type TD2 = keyof TD1; // 'a1' | 'a2' | 'b1' | 'b2'
type TD3<U> = keyof DoubleProp<U>; // `${keyof U & string}1` | `${keyof U & string}2`
>TD3 : `${keyof U & string}1` | `${keyof U & string}2`
// Repro from #40619
type Lazyify<T> = {
>Lazyify : Lazyify<T>
[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<Person>;
>LazyPerson : Lazyify<Person>
@@ -30,3 +30,17 @@ type DoubleProp<T> = { [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<U> = keyof DoubleProp<U>; // `${keyof U & string}1` | `${keyof U & string}2`
// Repro from #40619
type Lazyify<T> = {
[K in keyof T as `get${capitalize string & K}`]: () => T[K]
};
interface Person {
readonly name: string;
age: number;
location?: string;
}
type LazyPerson = Lazyify<Person>;