mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-13 06:20:23 -06:00
Merge pull request #28965 from Microsoft/simplifyIndexedAccess
Simplify indexed access types applied to mapped types
This commit is contained in:
commit
fecbdb68bd
@ -9686,26 +9686,15 @@ namespace ts {
|
||||
|
||||
// If the object type is a mapped type { [P in K]: E }, where K is generic, instantiate E using a mapper
|
||||
// that substitutes the index type for P. For example, for an index access { [P in K]: Box<T[P]> }[X], we
|
||||
// construct the type Box<T[X]>. We do not further simplify the result because mapped types can be recursive
|
||||
// and we might never terminate.
|
||||
// construct the type Box<T[X]>.
|
||||
if (isGenericMappedType(objectType)) {
|
||||
return type.simplified = substituteIndexedMappedType(objectType, type);
|
||||
}
|
||||
if (objectType.flags & TypeFlags.TypeParameter) {
|
||||
const constraint = getConstraintOfTypeParameter(objectType as TypeParameter);
|
||||
if (constraint && isGenericMappedType(constraint)) {
|
||||
return type.simplified = substituteIndexedMappedType(constraint, type);
|
||||
}
|
||||
const mapper = createTypeMapper([getTypeParameterFromMappedType(objectType)], [type.indexType]);
|
||||
const templateMapper = combineTypeMappers(objectType.mapper, mapper);
|
||||
return type.simplified = mapType(instantiateType(getTemplateTypeFromMappedType(objectType), templateMapper), getSimplifiedType);
|
||||
}
|
||||
return type.simplified = type;
|
||||
}
|
||||
|
||||
function substituteIndexedMappedType(objectType: MappedType, type: IndexedAccessType) {
|
||||
const mapper = createTypeMapper([getTypeParameterFromMappedType(objectType)], [type.indexType]);
|
||||
const templateMapper = combineTypeMappers(objectType.mapper, mapper);
|
||||
return instantiateType(getTemplateTypeFromMappedType(objectType), templateMapper);
|
||||
}
|
||||
|
||||
function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName, missingType = accessNode ? errorType : unknownType): Type {
|
||||
if (objectType === wildcardType || indexType === wildcardType) {
|
||||
return wildcardType;
|
||||
|
||||
@ -484,10 +484,10 @@ function onChangeGenericFunction<T>(handler: Handler<T & {preset: number}>) {
|
||||
function updateIds<T extends Record<K, string>, K extends string>(
|
||||
obj: T,
|
||||
idFields: K[],
|
||||
idMapping: { [oldId: string]: string }
|
||||
idMapping: Partial<Record<T[K], T[K]>>
|
||||
): Record<K, string> {
|
||||
for (const idField of idFields) {
|
||||
const newId = idMapping[obj[idField]];
|
||||
const newId: T[K] | undefined = idMapping[obj[idField]];
|
||||
if (newId) {
|
||||
obj[idField] = newId;
|
||||
}
|
||||
@ -1312,9 +1312,7 @@ declare type Handler<T> = {
|
||||
declare function onChangeGenericFunction<T>(handler: Handler<T & {
|
||||
preset: number;
|
||||
}>): void;
|
||||
declare function updateIds<T extends Record<K, string>, K extends string>(obj: T, idFields: K[], idMapping: {
|
||||
[oldId: string]: string;
|
||||
}): Record<K, string>;
|
||||
declare function updateIds<T extends Record<K, string>, K extends string>(obj: T, idFields: K[], idMapping: Partial<Record<T[K], T[K]>>): Record<K, string>;
|
||||
declare function updateIds2<T extends {
|
||||
[x: string]: string;
|
||||
}, K extends keyof T>(obj: T, key: K, stringMap: {
|
||||
|
||||
@ -1767,9 +1767,14 @@ function updateIds<T extends Record<K, string>, K extends string>(
|
||||
>idFields : Symbol(idFields, Decl(keyofAndIndexedAccess.ts, 483, 11))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 482, 47))
|
||||
|
||||
idMapping: { [oldId: string]: string }
|
||||
idMapping: Partial<Record<T[K], T[K]>>
|
||||
>idMapping : Symbol(idMapping, Decl(keyofAndIndexedAccess.ts, 484, 18))
|
||||
>oldId : Symbol(oldId, Decl(keyofAndIndexedAccess.ts, 485, 18))
|
||||
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 482, 19))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 482, 47))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 482, 19))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 482, 47))
|
||||
|
||||
): Record<K, string> {
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
@ -1779,8 +1784,10 @@ function updateIds<T extends Record<K, string>, K extends string>(
|
||||
>idField : Symbol(idField, Decl(keyofAndIndexedAccess.ts, 487, 14))
|
||||
>idFields : Symbol(idFields, Decl(keyofAndIndexedAccess.ts, 483, 11))
|
||||
|
||||
const newId = idMapping[obj[idField]];
|
||||
const newId: T[K] | undefined = idMapping[obj[idField]];
|
||||
>newId : Symbol(newId, Decl(keyofAndIndexedAccess.ts, 488, 13))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 482, 19))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 482, 47))
|
||||
>idMapping : Symbol(idMapping, Decl(keyofAndIndexedAccess.ts, 484, 18))
|
||||
>obj : Symbol(obj, Decl(keyofAndIndexedAccess.ts, 482, 66))
|
||||
>idField : Symbol(idField, Decl(keyofAndIndexedAccess.ts, 487, 14))
|
||||
|
||||
@ -1731,7 +1731,7 @@ function onChangeGenericFunction<T>(handler: Handler<T & {preset: number}>) {
|
||||
// Repro from #13285
|
||||
|
||||
function updateIds<T extends Record<K, string>, K extends string>(
|
||||
>updateIds : <T extends Record<K, string>, K extends string>(obj: T, idFields: K[], idMapping: { [oldId: string]: string; }) => Record<K, string>
|
||||
>updateIds : <T extends Record<K, string>, K extends string>(obj: T, idFields: K[], idMapping: Partial<Record<T[K], T[K]>>) => Record<K, string>
|
||||
|
||||
obj: T,
|
||||
>obj : T
|
||||
@ -1739,32 +1739,31 @@ function updateIds<T extends Record<K, string>, K extends string>(
|
||||
idFields: K[],
|
||||
>idFields : K[]
|
||||
|
||||
idMapping: { [oldId: string]: string }
|
||||
>idMapping : { [oldId: string]: string; }
|
||||
>oldId : string
|
||||
idMapping: Partial<Record<T[K], T[K]>>
|
||||
>idMapping : Partial<Record<T[K], T[K]>>
|
||||
|
||||
): Record<K, string> {
|
||||
for (const idField of idFields) {
|
||||
>idField : K
|
||||
>idFields : K[]
|
||||
|
||||
const newId = idMapping[obj[idField]];
|
||||
>newId : { [oldId: string]: string; }[T[K]]
|
||||
>idMapping[obj[idField]] : { [oldId: string]: string; }[T[K]]
|
||||
>idMapping : { [oldId: string]: string; }
|
||||
const newId: T[K] | undefined = idMapping[obj[idField]];
|
||||
>newId : T[K] | undefined
|
||||
>idMapping[obj[idField]] : Partial<Record<T[K], T[K]>>[T[K]]
|
||||
>idMapping : Partial<Record<T[K], T[K]>>
|
||||
>obj[idField] : T[K]
|
||||
>obj : T
|
||||
>idField : K
|
||||
|
||||
if (newId) {
|
||||
>newId : { [oldId: string]: string; }[T[K]]
|
||||
>newId : T[K] | undefined
|
||||
|
||||
obj[idField] = newId;
|
||||
>obj[idField] = newId : { [oldId: string]: string; }[T[K]]
|
||||
>obj[idField] = newId : T[K]
|
||||
>obj[idField] : T[K]
|
||||
>obj : T
|
||||
>idField : K
|
||||
>newId : { [oldId: string]: string; }[T[K]]
|
||||
>newId : T[K]
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
|
||||
@ -321,4 +321,14 @@ tests/cases/conformance/types/keyof/keyofAndIndexedAccessErrors.ts(142,5): error
|
||||
~~~~
|
||||
!!! error TS2322: Type 'number[]' is not assignable to type 'T[K]'.
|
||||
}
|
||||
|
||||
// Repro from #28839
|
||||
|
||||
function f30<T, K extends keyof T>() {
|
||||
let x: Partial<Record<keyof T, string>>[K] = "hello";
|
||||
}
|
||||
|
||||
function f31<T, K extends keyof T>() {
|
||||
let x: Partial<Partial<Partial<Partial<Partial<Partial<Partial<Record<keyof T, string>>>>>>>>[K] = "hello";
|
||||
}
|
||||
|
||||
@ -142,6 +142,16 @@ function test1<T extends Record<string, any>, K extends keyof T>(t: T, k: K) {
|
||||
t[k] = "hello"; // Error
|
||||
t[k] = [10, 20]; // Error
|
||||
}
|
||||
|
||||
// Repro from #28839
|
||||
|
||||
function f30<T, K extends keyof T>() {
|
||||
let x: Partial<Record<keyof T, string>>[K] = "hello";
|
||||
}
|
||||
|
||||
function f31<T, K extends keyof T>() {
|
||||
let x: Partial<Partial<Partial<Partial<Partial<Partial<Partial<Record<keyof T, string>>>>>>>>[K] = "hello";
|
||||
}
|
||||
|
||||
|
||||
//// [keyofAndIndexedAccessErrors.js]
|
||||
@ -215,3 +225,10 @@ function test1(t, k) {
|
||||
t[k] = "hello"; // Error
|
||||
t[k] = [10, 20]; // Error
|
||||
}
|
||||
// Repro from #28839
|
||||
function f30() {
|
||||
var x = "hello";
|
||||
}
|
||||
function f31() {
|
||||
var x = "hello";
|
||||
}
|
||||
|
||||
@ -486,3 +486,39 @@ function test1<T extends Record<string, any>, K extends keyof T>(t: T, k: K) {
|
||||
>k : Symbol(k, Decl(keyofAndIndexedAccessErrors.ts, 138, 70))
|
||||
}
|
||||
|
||||
// Repro from #28839
|
||||
|
||||
function f30<T, K extends keyof T>() {
|
||||
>f30 : Symbol(f30, Decl(keyofAndIndexedAccessErrors.ts, 142, 1))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 146, 13))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 146, 15))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 146, 13))
|
||||
|
||||
let x: Partial<Record<keyof T, string>>[K] = "hello";
|
||||
>x : Symbol(x, Decl(keyofAndIndexedAccessErrors.ts, 147, 7))
|
||||
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 146, 13))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 146, 15))
|
||||
}
|
||||
|
||||
function f31<T, K extends keyof T>() {
|
||||
>f31 : Symbol(f31, Decl(keyofAndIndexedAccessErrors.ts, 148, 1))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 150, 13))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 150, 15))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 150, 13))
|
||||
|
||||
let x: Partial<Partial<Partial<Partial<Partial<Partial<Partial<Record<keyof T, string>>>>>>>>[K] = "hello";
|
||||
>x : Symbol(x, Decl(keyofAndIndexedAccessErrors.ts, 151, 7))
|
||||
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
|
||||
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
|
||||
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
|
||||
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
|
||||
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
|
||||
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
|
||||
>Partial : Symbol(Partial, Decl(lib.es5.d.ts, --, --))
|
||||
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccessErrors.ts, 150, 13))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccessErrors.ts, 150, 15))
|
||||
}
|
||||
|
||||
|
||||
@ -465,3 +465,21 @@ function test1<T extends Record<string, any>, K extends keyof T>(t: T, k: K) {
|
||||
>20 : 20
|
||||
}
|
||||
|
||||
// Repro from #28839
|
||||
|
||||
function f30<T, K extends keyof T>() {
|
||||
>f30 : <T, K extends keyof T>() => void
|
||||
|
||||
let x: Partial<Record<keyof T, string>>[K] = "hello";
|
||||
>x : Partial<Record<keyof T, string>>[K]
|
||||
>"hello" : "hello"
|
||||
}
|
||||
|
||||
function f31<T, K extends keyof T>() {
|
||||
>f31 : <T, K extends keyof T>() => void
|
||||
|
||||
let x: Partial<Partial<Partial<Partial<Partial<Partial<Partial<Record<keyof T, string>>>>>>>>[K] = "hello";
|
||||
>x : Partial<Partial<Partial<Partial<Partial<Partial<Partial<Record<keyof T, string>>>>>>>>[K]
|
||||
>"hello" : "hello"
|
||||
}
|
||||
|
||||
|
||||
@ -486,10 +486,10 @@ function onChangeGenericFunction<T>(handler: Handler<T & {preset: number}>) {
|
||||
function updateIds<T extends Record<K, string>, K extends string>(
|
||||
obj: T,
|
||||
idFields: K[],
|
||||
idMapping: { [oldId: string]: string }
|
||||
idMapping: Partial<Record<T[K], T[K]>>
|
||||
): Record<K, string> {
|
||||
for (const idField of idFields) {
|
||||
const newId = idMapping[obj[idField]];
|
||||
const newId: T[K] | undefined = idMapping[obj[idField]];
|
||||
if (newId) {
|
||||
obj[idField] = newId;
|
||||
}
|
||||
|
||||
@ -141,3 +141,13 @@ function test1<T extends Record<string, any>, K extends keyof T>(t: T, k: K) {
|
||||
t[k] = "hello"; // Error
|
||||
t[k] = [10, 20]; // Error
|
||||
}
|
||||
|
||||
// Repro from #28839
|
||||
|
||||
function f30<T, K extends keyof T>() {
|
||||
let x: Partial<Record<keyof T, string>>[K] = "hello";
|
||||
}
|
||||
|
||||
function f31<T, K extends keyof T>() {
|
||||
let x: Partial<Partial<Partial<Partial<Partial<Partial<Partial<Record<keyof T, string>>>>>>>>[K] = "hello";
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user