Merge pull request #18391 from Microsoft/fixMappedTypeInference
Inference for higher order mapped, index and lookup types
This commit is contained in:
commit
d90814bc57
5 changed files with 284 additions and 1 deletions
|
@ -10387,7 +10387,7 @@ namespace ts {
|
|||
// results for union and intersection types for performance reasons.
|
||||
function couldContainTypeVariables(type: Type): boolean {
|
||||
const objectFlags = getObjectFlags(type);
|
||||
return !!(type.flags & TypeFlags.TypeVariable ||
|
||||
return !!(type.flags & (TypeFlags.TypeVariable | TypeFlags.Index) ||
|
||||
objectFlags & ObjectFlags.Reference && forEach((<TypeReference>type).typeArguments, couldContainTypeVariables) ||
|
||||
objectFlags & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) ||
|
||||
objectFlags & ObjectFlags.Mapped ||
|
||||
|
@ -10555,6 +10555,13 @@ namespace ts {
|
|||
inferFromTypes(sourceTypes[i], targetTypes[i]);
|
||||
}
|
||||
}
|
||||
else if (source.flags & TypeFlags.Index && target.flags & TypeFlags.Index) {
|
||||
inferFromTypes((<IndexType>source).type, (<IndexType>target).type);
|
||||
}
|
||||
else if (source.flags & TypeFlags.IndexedAccess && target.flags & TypeFlags.IndexedAccess) {
|
||||
inferFromTypes((<IndexedAccessType>source).objectType, (<IndexedAccessType>target).objectType);
|
||||
inferFromTypes((<IndexedAccessType>source).indexType, (<IndexedAccessType>target).indexType);
|
||||
}
|
||||
else if (target.flags & TypeFlags.UnionOrIntersection) {
|
||||
const targetTypes = (<UnionOrIntersectionType>target).types;
|
||||
let typeVariableCount = 0;
|
||||
|
@ -10628,6 +10635,12 @@ namespace ts {
|
|||
}
|
||||
|
||||
function inferFromObjectTypes(source: Type, target: Type) {
|
||||
if (isGenericMappedType(source) && isGenericMappedType(target)) {
|
||||
// The source and target types are generic types { [P in S]: X } and { [P in T]: Y }, so we infer
|
||||
// from S to T and from X to Y.
|
||||
inferFromTypes(getConstraintTypeFromMappedType(<MappedType>source), getConstraintTypeFromMappedType(<MappedType>target));
|
||||
inferFromTypes(getTemplateTypeFromMappedType(<MappedType>source), getTemplateTypeFromMappedType(<MappedType>target));
|
||||
}
|
||||
if (getObjectFlags(target) & ObjectFlags.Mapped) {
|
||||
const constraintType = getConstraintTypeFromMappedType(<MappedType>target);
|
||||
if (constraintType.flags & TypeFlags.Index) {
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
//// [higherOrderMappedIndexLookupInference.ts]
|
||||
// @strict
|
||||
|
||||
function f1(a: <T>() => keyof T, b: <U>() => keyof U) {
|
||||
a = b;
|
||||
b = a;
|
||||
}
|
||||
|
||||
function f2(a: <T, K extends keyof T>() => T[K], b: <U, L extends keyof U>() => U[L]) {
|
||||
a = b;
|
||||
b = a;
|
||||
}
|
||||
|
||||
function f3(a: <T>() => { [K in keyof T]: T[K] }, b: <U>() => { [K in keyof U]: U[K] }) {
|
||||
a = b;
|
||||
b = a;
|
||||
}
|
||||
|
||||
// Repro from #18338
|
||||
|
||||
type IdMapped<T> = { [K in keyof T]: T[K] }
|
||||
|
||||
declare const f: <T>() => IdMapped<T>;
|
||||
declare const g: <U>() => { [K in keyof U]: U[K] };
|
||||
|
||||
const h: typeof g = f;
|
||||
|
||||
|
||||
//// [higherOrderMappedIndexLookupInference.js]
|
||||
// @strict
|
||||
function f1(a, b) {
|
||||
a = b;
|
||||
b = a;
|
||||
}
|
||||
function f2(a, b) {
|
||||
a = b;
|
||||
b = a;
|
||||
}
|
||||
function f3(a, b) {
|
||||
a = b;
|
||||
b = a;
|
||||
}
|
||||
var h = f;
|
|
@ -0,0 +1,98 @@
|
|||
=== tests/cases/compiler/higherOrderMappedIndexLookupInference.ts ===
|
||||
// @strict
|
||||
|
||||
function f1(a: <T>() => keyof T, b: <U>() => keyof U) {
|
||||
>f1 : Symbol(f1, Decl(higherOrderMappedIndexLookupInference.ts, 0, 0))
|
||||
>a : Symbol(a, Decl(higherOrderMappedIndexLookupInference.ts, 2, 12))
|
||||
>T : Symbol(T, Decl(higherOrderMappedIndexLookupInference.ts, 2, 16))
|
||||
>T : Symbol(T, Decl(higherOrderMappedIndexLookupInference.ts, 2, 16))
|
||||
>b : Symbol(b, Decl(higherOrderMappedIndexLookupInference.ts, 2, 32))
|
||||
>U : Symbol(U, Decl(higherOrderMappedIndexLookupInference.ts, 2, 37))
|
||||
>U : Symbol(U, Decl(higherOrderMappedIndexLookupInference.ts, 2, 37))
|
||||
|
||||
a = b;
|
||||
>a : Symbol(a, Decl(higherOrderMappedIndexLookupInference.ts, 2, 12))
|
||||
>b : Symbol(b, Decl(higherOrderMappedIndexLookupInference.ts, 2, 32))
|
||||
|
||||
b = a;
|
||||
>b : Symbol(b, Decl(higherOrderMappedIndexLookupInference.ts, 2, 32))
|
||||
>a : Symbol(a, Decl(higherOrderMappedIndexLookupInference.ts, 2, 12))
|
||||
}
|
||||
|
||||
function f2(a: <T, K extends keyof T>() => T[K], b: <U, L extends keyof U>() => U[L]) {
|
||||
>f2 : Symbol(f2, Decl(higherOrderMappedIndexLookupInference.ts, 5, 1))
|
||||
>a : Symbol(a, Decl(higherOrderMappedIndexLookupInference.ts, 7, 12))
|
||||
>T : Symbol(T, Decl(higherOrderMappedIndexLookupInference.ts, 7, 16))
|
||||
>K : Symbol(K, Decl(higherOrderMappedIndexLookupInference.ts, 7, 18))
|
||||
>T : Symbol(T, Decl(higherOrderMappedIndexLookupInference.ts, 7, 16))
|
||||
>T : Symbol(T, Decl(higherOrderMappedIndexLookupInference.ts, 7, 16))
|
||||
>K : Symbol(K, Decl(higherOrderMappedIndexLookupInference.ts, 7, 18))
|
||||
>b : Symbol(b, Decl(higherOrderMappedIndexLookupInference.ts, 7, 48))
|
||||
>U : Symbol(U, Decl(higherOrderMappedIndexLookupInference.ts, 7, 53))
|
||||
>L : Symbol(L, Decl(higherOrderMappedIndexLookupInference.ts, 7, 55))
|
||||
>U : Symbol(U, Decl(higherOrderMappedIndexLookupInference.ts, 7, 53))
|
||||
>U : Symbol(U, Decl(higherOrderMappedIndexLookupInference.ts, 7, 53))
|
||||
>L : Symbol(L, Decl(higherOrderMappedIndexLookupInference.ts, 7, 55))
|
||||
|
||||
a = b;
|
||||
>a : Symbol(a, Decl(higherOrderMappedIndexLookupInference.ts, 7, 12))
|
||||
>b : Symbol(b, Decl(higherOrderMappedIndexLookupInference.ts, 7, 48))
|
||||
|
||||
b = a;
|
||||
>b : Symbol(b, Decl(higherOrderMappedIndexLookupInference.ts, 7, 48))
|
||||
>a : Symbol(a, Decl(higherOrderMappedIndexLookupInference.ts, 7, 12))
|
||||
}
|
||||
|
||||
function f3(a: <T>() => { [K in keyof T]: T[K] }, b: <U>() => { [K in keyof U]: U[K] }) {
|
||||
>f3 : Symbol(f3, Decl(higherOrderMappedIndexLookupInference.ts, 10, 1))
|
||||
>a : Symbol(a, Decl(higherOrderMappedIndexLookupInference.ts, 12, 12))
|
||||
>T : Symbol(T, Decl(higherOrderMappedIndexLookupInference.ts, 12, 16))
|
||||
>K : Symbol(K, Decl(higherOrderMappedIndexLookupInference.ts, 12, 27))
|
||||
>T : Symbol(T, Decl(higherOrderMappedIndexLookupInference.ts, 12, 16))
|
||||
>T : Symbol(T, Decl(higherOrderMappedIndexLookupInference.ts, 12, 16))
|
||||
>K : Symbol(K, Decl(higherOrderMappedIndexLookupInference.ts, 12, 27))
|
||||
>b : Symbol(b, Decl(higherOrderMappedIndexLookupInference.ts, 12, 49))
|
||||
>U : Symbol(U, Decl(higherOrderMappedIndexLookupInference.ts, 12, 54))
|
||||
>K : Symbol(K, Decl(higherOrderMappedIndexLookupInference.ts, 12, 65))
|
||||
>U : Symbol(U, Decl(higherOrderMappedIndexLookupInference.ts, 12, 54))
|
||||
>U : Symbol(U, Decl(higherOrderMappedIndexLookupInference.ts, 12, 54))
|
||||
>K : Symbol(K, Decl(higherOrderMappedIndexLookupInference.ts, 12, 65))
|
||||
|
||||
a = b;
|
||||
>a : Symbol(a, Decl(higherOrderMappedIndexLookupInference.ts, 12, 12))
|
||||
>b : Symbol(b, Decl(higherOrderMappedIndexLookupInference.ts, 12, 49))
|
||||
|
||||
b = a;
|
||||
>b : Symbol(b, Decl(higherOrderMappedIndexLookupInference.ts, 12, 49))
|
||||
>a : Symbol(a, Decl(higherOrderMappedIndexLookupInference.ts, 12, 12))
|
||||
}
|
||||
|
||||
// Repro from #18338
|
||||
|
||||
type IdMapped<T> = { [K in keyof T]: T[K] }
|
||||
>IdMapped : Symbol(IdMapped, Decl(higherOrderMappedIndexLookupInference.ts, 15, 1))
|
||||
>T : Symbol(T, Decl(higherOrderMappedIndexLookupInference.ts, 19, 14))
|
||||
>K : Symbol(K, Decl(higherOrderMappedIndexLookupInference.ts, 19, 22))
|
||||
>T : Symbol(T, Decl(higherOrderMappedIndexLookupInference.ts, 19, 14))
|
||||
>T : Symbol(T, Decl(higherOrderMappedIndexLookupInference.ts, 19, 14))
|
||||
>K : Symbol(K, Decl(higherOrderMappedIndexLookupInference.ts, 19, 22))
|
||||
|
||||
declare const f: <T>() => IdMapped<T>;
|
||||
>f : Symbol(f, Decl(higherOrderMappedIndexLookupInference.ts, 21, 13))
|
||||
>T : Symbol(T, Decl(higherOrderMappedIndexLookupInference.ts, 21, 18))
|
||||
>IdMapped : Symbol(IdMapped, Decl(higherOrderMappedIndexLookupInference.ts, 15, 1))
|
||||
>T : Symbol(T, Decl(higherOrderMappedIndexLookupInference.ts, 21, 18))
|
||||
|
||||
declare const g: <U>() => { [K in keyof U]: U[K] };
|
||||
>g : Symbol(g, Decl(higherOrderMappedIndexLookupInference.ts, 22, 13))
|
||||
>U : Symbol(U, Decl(higherOrderMappedIndexLookupInference.ts, 22, 18))
|
||||
>K : Symbol(K, Decl(higherOrderMappedIndexLookupInference.ts, 22, 29))
|
||||
>U : Symbol(U, Decl(higherOrderMappedIndexLookupInference.ts, 22, 18))
|
||||
>U : Symbol(U, Decl(higherOrderMappedIndexLookupInference.ts, 22, 18))
|
||||
>K : Symbol(K, Decl(higherOrderMappedIndexLookupInference.ts, 22, 29))
|
||||
|
||||
const h: typeof g = f;
|
||||
>h : Symbol(h, Decl(higherOrderMappedIndexLookupInference.ts, 24, 5))
|
||||
>g : Symbol(g, Decl(higherOrderMappedIndexLookupInference.ts, 22, 13))
|
||||
>f : Symbol(f, Decl(higherOrderMappedIndexLookupInference.ts, 21, 13))
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
=== tests/cases/compiler/higherOrderMappedIndexLookupInference.ts ===
|
||||
// @strict
|
||||
|
||||
function f1(a: <T>() => keyof T, b: <U>() => keyof U) {
|
||||
>f1 : (a: <T>() => keyof T, b: <U>() => keyof U) => void
|
||||
>a : <T>() => keyof T
|
||||
>T : T
|
||||
>T : T
|
||||
>b : <U>() => keyof U
|
||||
>U : U
|
||||
>U : U
|
||||
|
||||
a = b;
|
||||
>a = b : <U>() => keyof U
|
||||
>a : <T>() => keyof T
|
||||
>b : <U>() => keyof U
|
||||
|
||||
b = a;
|
||||
>b = a : <T>() => keyof T
|
||||
>b : <U>() => keyof U
|
||||
>a : <T>() => keyof T
|
||||
}
|
||||
|
||||
function f2(a: <T, K extends keyof T>() => T[K], b: <U, L extends keyof U>() => U[L]) {
|
||||
>f2 : (a: <T, K extends keyof T>() => T[K], b: <U, L extends keyof U>() => U[L]) => void
|
||||
>a : <T, K extends keyof T>() => T[K]
|
||||
>T : T
|
||||
>K : K
|
||||
>T : T
|
||||
>T : T
|
||||
>K : K
|
||||
>b : <U, L extends keyof U>() => U[L]
|
||||
>U : U
|
||||
>L : L
|
||||
>U : U
|
||||
>U : U
|
||||
>L : L
|
||||
|
||||
a = b;
|
||||
>a = b : <U, L extends keyof U>() => U[L]
|
||||
>a : <T, K extends keyof T>() => T[K]
|
||||
>b : <U, L extends keyof U>() => U[L]
|
||||
|
||||
b = a;
|
||||
>b = a : <T, K extends keyof T>() => T[K]
|
||||
>b : <U, L extends keyof U>() => U[L]
|
||||
>a : <T, K extends keyof T>() => T[K]
|
||||
}
|
||||
|
||||
function f3(a: <T>() => { [K in keyof T]: T[K] }, b: <U>() => { [K in keyof U]: U[K] }) {
|
||||
>f3 : (a: <T>() => { [K in keyof T]: T[K]; }, b: <U>() => { [K in keyof U]: U[K]; }) => void
|
||||
>a : <T>() => { [K in keyof T]: T[K]; }
|
||||
>T : T
|
||||
>K : K
|
||||
>T : T
|
||||
>T : T
|
||||
>K : K
|
||||
>b : <U>() => { [K in keyof U]: U[K]; }
|
||||
>U : U
|
||||
>K : K
|
||||
>U : U
|
||||
>U : U
|
||||
>K : K
|
||||
|
||||
a = b;
|
||||
>a = b : <U>() => { [K in keyof U]: U[K]; }
|
||||
>a : <T>() => { [K in keyof T]: T[K]; }
|
||||
>b : <U>() => { [K in keyof U]: U[K]; }
|
||||
|
||||
b = a;
|
||||
>b = a : <T>() => { [K in keyof T]: T[K]; }
|
||||
>b : <U>() => { [K in keyof U]: U[K]; }
|
||||
>a : <T>() => { [K in keyof T]: T[K]; }
|
||||
}
|
||||
|
||||
// Repro from #18338
|
||||
|
||||
type IdMapped<T> = { [K in keyof T]: T[K] }
|
||||
>IdMapped : IdMapped<T>
|
||||
>T : T
|
||||
>K : K
|
||||
>T : T
|
||||
>T : T
|
||||
>K : K
|
||||
|
||||
declare const f: <T>() => IdMapped<T>;
|
||||
>f : <T>() => IdMapped<T>
|
||||
>T : T
|
||||
>IdMapped : IdMapped<T>
|
||||
>T : T
|
||||
|
||||
declare const g: <U>() => { [K in keyof U]: U[K] };
|
||||
>g : <U>() => { [K in keyof U]: U[K]; }
|
||||
>U : U
|
||||
>K : K
|
||||
>U : U
|
||||
>U : U
|
||||
>K : K
|
||||
|
||||
const h: typeof g = f;
|
||||
>h : <U>() => { [K in keyof U]: U[K]; }
|
||||
>g : <U>() => { [K in keyof U]: U[K]; }
|
||||
>f : <T>() => IdMapped<T>
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// @strict
|
||||
|
||||
function f1(a: <T>() => keyof T, b: <U>() => keyof U) {
|
||||
a = b;
|
||||
b = a;
|
||||
}
|
||||
|
||||
function f2(a: <T, K extends keyof T>() => T[K], b: <U, L extends keyof U>() => U[L]) {
|
||||
a = b;
|
||||
b = a;
|
||||
}
|
||||
|
||||
function f3(a: <T>() => { [K in keyof T]: T[K] }, b: <U>() => { [K in keyof U]: U[K] }) {
|
||||
a = b;
|
||||
b = a;
|
||||
}
|
||||
|
||||
// Repro from #18338
|
||||
|
||||
type IdMapped<T> = { [K in keyof T]: T[K] }
|
||||
|
||||
declare const f: <T>() => IdMapped<T>;
|
||||
declare const g: <U>() => { [K in keyof U]: U[K] };
|
||||
|
||||
const h: typeof g = f;
|
Loading…
Reference in a new issue