Skip to content

Commit 13ce0e9

Browse files
committed
Fix type relations for 'keyof T' type where T is union or intersection
1 parent 5e6c5ef commit 13ce0e9

File tree

2 files changed

+20
-20
lines changed

2 files changed

+20
-20
lines changed

src/compiler/checker.ts

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4753,15 +4753,15 @@ namespace ts {
47534753
getPropertiesOfObjectType(type);
47544754
}
47554755

4756-
function getConstraintOfTypeVariable(type: TypeVariable): Type {
4757-
return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>type) : getBaseConstraintOfTypeVariable(type);
4756+
function getConstraintOfType(type: TypeVariable | UnionOrIntersectionType): Type {
4757+
return type.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>type) : getBaseConstraintOfType(type);
47584758
}
47594759

47604760
function getConstraintOfTypeParameter(typeParameter: TypeParameter): Type {
47614761
return hasNonCircularBaseConstraint(typeParameter) ? getConstraintFromTypeParameter(typeParameter) : undefined;
47624762
}
47634763

4764-
function getBaseConstraintOfTypeVariable(type: TypeVariable): Type {
4764+
function getBaseConstraintOfType(type: TypeVariable | UnionOrIntersectionType): Type {
47654765
const constraint = getResolvedBaseConstraint(type);
47664766
return constraint !== noConstraintType && constraint !== circularConstraintType ? constraint : undefined;
47674767
}
@@ -4775,15 +4775,15 @@ namespace ts {
47754775
* type variable has no constraint, and the circularConstraintType singleton is returned if the constraint
47764776
* circularly references the type variable.
47774777
*/
4778-
function getResolvedBaseConstraint(type: TypeVariable): Type {
4778+
function getResolvedBaseConstraint(type: TypeVariable | UnionOrIntersectionType): Type {
47794779
let typeStack: Type[];
47804780
let circular: boolean;
4781-
if (!type.resolvedApparentType) {
4781+
if (!type.resolvedBaseConstraint) {
47824782
typeStack = [];
47834783
const constraint = getBaseConstraint(type);
4784-
type.resolvedApparentType = circular ? circularConstraintType : getTypeWithThisArgument(constraint || noConstraintType, type);
4784+
type.resolvedBaseConstraint = circular ? circularConstraintType : getTypeWithThisArgument(constraint || noConstraintType, type);
47854785
}
4786-
return type.resolvedApparentType;
4786+
return type.resolvedBaseConstraint;
47874787

47884788
function getBaseConstraint(t: Type): Type {
47894789
if (contains(typeStack, t)) {
@@ -4834,7 +4834,7 @@ namespace ts {
48344834
* type itself. Note that the apparent type of a union type is the union type itself.
48354835
*/
48364836
function getApparentType(type: Type): Type {
4837-
const t = type.flags & TypeFlags.TypeVariable ? getBaseConstraintOfTypeVariable(<TypeVariable>type) || emptyObjectType : type;
4837+
const t = type.flags & TypeFlags.TypeVariable ? getBaseConstraintOfType(<TypeVariable>type) || emptyObjectType : type;
48384838
return t.flags & TypeFlags.StringLike ? globalStringType :
48394839
t.flags & TypeFlags.NumberLike ? globalNumberType :
48404840
t.flags & TypeFlags.BooleanLike ? globalBooleanType :
@@ -7427,14 +7427,12 @@ namespace ts {
74277427
return result;
74287428
}
74297429
}
7430-
// Given a type variable T with a constraint C, a type S is assignable to
7431-
// keyof T if S is assignable to keyof C.
7432-
if ((<IndexType>target).type.flags & TypeFlags.TypeVariable) {
7433-
const constraint = getConstraintOfTypeVariable(<TypeVariable>(<IndexType>target).type);
7434-
if (constraint) {
7435-
if (result = isRelatedTo(source, getIndexType(constraint), reportErrors)) {
7436-
return result;
7437-
}
7430+
// A type S is assignable to keyof T if S is assignable to keyof C, where C is the
7431+
// constraint of T.
7432+
const constraint = getConstraintOfType((<IndexType>target).type);
7433+
if (constraint) {
7434+
if (result = isRelatedTo(source, getIndexType(constraint), reportErrors)) {
7435+
return result;
74387436
}
74397437
}
74407438
}
@@ -7448,7 +7446,7 @@ namespace ts {
74487446
}
74497447
// A type S is related to a type T[K] if S is related to A[K], where K is string-like and
74507448
// A is the apparent type of S.
7451-
const constraint = getBaseConstraintOfTypeVariable(<IndexedAccessType>target);
7449+
const constraint = getBaseConstraintOfType(<IndexedAccessType>target);
74527450
if (constraint) {
74537451
if (result = isRelatedTo(source, constraint, reportErrors)) {
74547452
errorInfo = saveErrorInfo;
@@ -7488,7 +7486,7 @@ namespace ts {
74887486
else if (source.flags & TypeFlags.IndexedAccess) {
74897487
// A type S[K] is related to a type T if A[K] is related to T, where K is string-like and
74907488
// A is the apparent type of S.
7491-
const constraint = getBaseConstraintOfTypeVariable(<IndexedAccessType>source);
7489+
const constraint = getBaseConstraintOfType(<IndexedAccessType>source);
74927490
if (constraint) {
74937491
if (result = isRelatedTo(constraint, target, reportErrors)) {
74947492
errorInfo = saveErrorInfo;
@@ -15207,7 +15205,7 @@ namespace ts {
1520715205
function isLiteralContextualType(contextualType: Type) {
1520815206
if (contextualType) {
1520915207
if (contextualType.flags & TypeFlags.TypeVariable) {
15210-
const constraint = getBaseConstraintOfTypeVariable(<TypeVariable>contextualType) || emptyObjectType;
15208+
const constraint = getBaseConstraintOfType(<TypeVariable>contextualType) || emptyObjectType;
1521115209
// If the type parameter is constrained to the base primitive type we're checking for,
1521215210
// consider this a literal context. For example, given a type parameter 'T extends string',
1521315211
// this causes us to infer string literal types for T.

src/compiler/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2923,6 +2923,8 @@ namespace ts {
29232923
/* @internal */
29242924
resolvedIndexType: IndexType;
29252925
/* @internal */
2926+
resolvedBaseConstraint: Type;
2927+
/* @internal */
29262928
couldContainTypeVariables: boolean;
29272929
}
29282930

@@ -2982,7 +2984,7 @@ namespace ts {
29822984

29832985
export interface TypeVariable extends Type {
29842986
/* @internal */
2985-
resolvedApparentType: Type;
2987+
resolvedBaseConstraint: Type;
29862988
/* @internal */
29872989
resolvedIndexType: IndexType;
29882990
}

0 commit comments

Comments
 (0)