mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-23 17:30:04 -05:00
Merge pull request #26698 from Microsoft/indexedAccessConstraints
Improve indexed access type relations
This commit is contained in:
@@ -6905,10 +6905,15 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getConstraintOfIndexedAccess(type: IndexedAccessType) {
|
||||
const objectType = getBaseConstraintOfType(type.objectType) || type.objectType;
|
||||
const indexType = getBaseConstraintOfType(type.indexType) || type.indexType;
|
||||
const constraint = !isGenericObjectType(objectType) && !isGenericIndexType(indexType) ? getIndexedAccessType(objectType, indexType, /*accessNode*/ undefined, errorType) : undefined;
|
||||
return constraint && constraint !== errorType ? constraint : undefined;
|
||||
const objectType = getConstraintOfType(type.objectType) || type.objectType;
|
||||
if (objectType !== type.objectType) {
|
||||
const constraint = getIndexedAccessType(objectType, type.indexType, /*accessNode*/ undefined, errorType);
|
||||
if (constraint && constraint !== errorType) {
|
||||
return constraint;
|
||||
}
|
||||
}
|
||||
const baseConstraint = getBaseConstraintOfType(type);
|
||||
return baseConstraint && baseConstraint !== type ? baseConstraint : undefined;
|
||||
}
|
||||
|
||||
function getDefaultConstraintOfConditionalType(type: ConditionalType) {
|
||||
@@ -7080,9 +7085,6 @@ namespace ts {
|
||||
if (t.flags & TypeFlags.Substitution) {
|
||||
return getBaseConstraint((<SubstitutionType>t).substitute);
|
||||
}
|
||||
if (isGenericMappedType(t)) {
|
||||
return emptyObjectType;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
@@ -11648,12 +11650,13 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else if (target.flags & TypeFlags.IndexedAccess) {
|
||||
// A type S is related to a type T[K] if S is related to C, where C is the
|
||||
// constraint of T[K]
|
||||
const constraint = getConstraintForRelation(target);
|
||||
if (constraint) {
|
||||
if (result = isRelatedTo(source, constraint, reportErrors)) {
|
||||
return result;
|
||||
// A type S is related to a type T[K] if S is related to C, where C is the base constraint of T[K]
|
||||
if (relation !== identityRelation) {
|
||||
const constraint = getBaseConstraintOfType(target);
|
||||
if (constraint && constraint !== target) {
|
||||
if (result = isRelatedTo(source, constraint, reportErrors)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -649,6 +649,20 @@ function ff2<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2:
|
||||
const d: Dict<T> = dd[k1];
|
||||
return d[k2];
|
||||
}
|
||||
|
||||
// Repro from #26409
|
||||
|
||||
const cf1 = <T extends { [P in K]: string; } & { cool: string; }, K extends keyof T>(t: T, k: K) =>
|
||||
{
|
||||
const s: string = t[k];
|
||||
t.cool;
|
||||
};
|
||||
|
||||
const cf2 = <T extends { [P in K | "cool"]: string; }, K extends keyof T>(t: T, k: K) =>
|
||||
{
|
||||
const s: string = t[k];
|
||||
t.cool;
|
||||
};
|
||||
|
||||
|
||||
//// [keyofAndIndexedAccess.js]
|
||||
@@ -1078,6 +1092,15 @@ function ff2(dd, k1, k2) {
|
||||
var d = dd[k1];
|
||||
return d[k2];
|
||||
}
|
||||
// Repro from #26409
|
||||
var cf1 = function (t, k) {
|
||||
var s = t[k];
|
||||
t.cool;
|
||||
};
|
||||
var cf2 = function (t, k) {
|
||||
var s = t[k];
|
||||
t.cool;
|
||||
};
|
||||
|
||||
|
||||
//// [keyofAndIndexedAccess.d.ts]
|
||||
@@ -1413,3 +1436,7 @@ declare type DictDict<V extends string, T extends string> = {
|
||||
};
|
||||
declare function ff1<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T): number;
|
||||
declare function ff2<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2: T): number;
|
||||
declare const cf1: <T extends { [P in K]: string; } & {
|
||||
cool: string;
|
||||
}, K extends keyof T>(t: T, k: K) => void;
|
||||
declare const cf2: <T extends { [P in K | "cool"]: string; }, K extends keyof T>(t: T, k: K) => void;
|
||||
|
||||
@@ -2319,3 +2319,54 @@ function ff2<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2:
|
||||
>k2 : Symbol(k2, Decl(keyofAndIndexedAccess.ts, 646, 75))
|
||||
}
|
||||
|
||||
// Repro from #26409
|
||||
|
||||
const cf1 = <T extends { [P in K]: string; } & { cool: string; }, K extends keyof T>(t: T, k: K) =>
|
||||
>cf1 : Symbol(cf1, Decl(keyofAndIndexedAccess.ts, 653, 5))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 653, 13))
|
||||
>P : Symbol(P, Decl(keyofAndIndexedAccess.ts, 653, 26))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 653, 65))
|
||||
>cool : Symbol(cool, Decl(keyofAndIndexedAccess.ts, 653, 48))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 653, 65))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 653, 13))
|
||||
>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 653, 85))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 653, 13))
|
||||
>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 653, 90))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 653, 65))
|
||||
{
|
||||
const s: string = t[k];
|
||||
>s : Symbol(s, Decl(keyofAndIndexedAccess.ts, 655, 9))
|
||||
>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 653, 85))
|
||||
>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 653, 90))
|
||||
|
||||
t.cool;
|
||||
>t.cool : Symbol(cool, Decl(keyofAndIndexedAccess.ts, 653, 48))
|
||||
>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 653, 85))
|
||||
>cool : Symbol(cool, Decl(keyofAndIndexedAccess.ts, 653, 48))
|
||||
|
||||
};
|
||||
|
||||
const cf2 = <T extends { [P in K | "cool"]: string; }, K extends keyof T>(t: T, k: K) =>
|
||||
>cf2 : Symbol(cf2, Decl(keyofAndIndexedAccess.ts, 659, 5))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 659, 13))
|
||||
>P : Symbol(P, Decl(keyofAndIndexedAccess.ts, 659, 26))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 659, 54))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 659, 54))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 659, 13))
|
||||
>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 659, 74))
|
||||
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 659, 13))
|
||||
>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 659, 79))
|
||||
>K : Symbol(K, Decl(keyofAndIndexedAccess.ts, 659, 54))
|
||||
{
|
||||
const s: string = t[k];
|
||||
>s : Symbol(s, Decl(keyofAndIndexedAccess.ts, 661, 9))
|
||||
>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 659, 74))
|
||||
>k : Symbol(k, Decl(keyofAndIndexedAccess.ts, 659, 79))
|
||||
|
||||
t.cool;
|
||||
>t.cool : Symbol(cool)
|
||||
>t : Symbol(t, Decl(keyofAndIndexedAccess.ts, 659, 74))
|
||||
>cool : Symbol(cool)
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -2184,3 +2184,44 @@ function ff2<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2:
|
||||
>k2 : T
|
||||
}
|
||||
|
||||
// Repro from #26409
|
||||
|
||||
const cf1 = <T extends { [P in K]: string; } & { cool: string; }, K extends keyof T>(t: T, k: K) =>
|
||||
>cf1 : <T extends { [P in K]: string; } & { cool: string; }, K extends keyof T>(t: T, k: K) => void
|
||||
><T extends { [P in K]: string; } & { cool: string; }, K extends keyof T>(t: T, k: K) =>{ const s: string = t[k]; t.cool;} : <T extends { [P in K]: string; } & { cool: string; }, K extends keyof T>(t: T, k: K) => void
|
||||
>cool : string
|
||||
>t : T
|
||||
>k : K
|
||||
{
|
||||
const s: string = t[k];
|
||||
>s : string
|
||||
>t[k] : T[K]
|
||||
>t : T
|
||||
>k : K
|
||||
|
||||
t.cool;
|
||||
>t.cool : string
|
||||
>t : T
|
||||
>cool : string
|
||||
|
||||
};
|
||||
|
||||
const cf2 = <T extends { [P in K | "cool"]: string; }, K extends keyof T>(t: T, k: K) =>
|
||||
>cf2 : <T extends { [P in K | "cool"]: string; }, K extends keyof T>(t: T, k: K) => void
|
||||
><T extends { [P in K | "cool"]: string; }, K extends keyof T>(t: T, k: K) =>{ const s: string = t[k]; t.cool;} : <T extends { [P in K | "cool"]: string; }, K extends keyof T>(t: T, k: K) => void
|
||||
>t : T
|
||||
>k : K
|
||||
{
|
||||
const s: string = t[k];
|
||||
>s : string
|
||||
>t[k] : T[K]
|
||||
>t : T
|
||||
>k : K
|
||||
|
||||
t.cool;
|
||||
>t.cool : string
|
||||
>t : T
|
||||
>cool : string
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -651,3 +651,17 @@ function ff2<V extends string, T extends string>(dd: DictDict<V, T>, k1: V, k2:
|
||||
const d: Dict<T> = dd[k1];
|
||||
return d[k2];
|
||||
}
|
||||
|
||||
// Repro from #26409
|
||||
|
||||
const cf1 = <T extends { [P in K]: string; } & { cool: string; }, K extends keyof T>(t: T, k: K) =>
|
||||
{
|
||||
const s: string = t[k];
|
||||
t.cool;
|
||||
};
|
||||
|
||||
const cf2 = <T extends { [P in K | "cool"]: string; }, K extends keyof T>(t: T, k: K) =>
|
||||
{
|
||||
const s: string = t[k];
|
||||
t.cool;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user