Skip to content

Commit 6f681d2

Browse files
committed
Constraint of 'T extends U ? T : F' should be 'T & U | F'
1 parent a9aca81 commit 6f681d2

File tree

2 files changed

+24
-10
lines changed

2 files changed

+24
-10
lines changed

src/compiler/checker.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6233,7 +6233,12 @@ namespace ts {
62336233
}
62346234

62356235
function getDefaultConstraintOfConditionalType(type: ConditionalType) {
6236-
return getUnionType([getInferredTrueTypeFromConditionalType(type), getFalseTypeFromConditionalType(type)]);
6236+
if (!type.resolvedDefaultConstraint) {
6237+
const rootTrueType = type.root.trueType;
6238+
const rootTrueConstraint = rootTrueType.flags & TypeFlags.Substitution ? (<SubstitutionType>rootTrueType).substitute : rootTrueType;
6239+
type.resolvedDefaultConstraint = getUnionType([instantiateType(rootTrueConstraint, type.combinedMapper || type.mapper), getFalseTypeFromConditionalType(type)]);
6240+
}
6241+
return type.resolvedDefaultConstraint;
62376242
}
62386243

62396244
function getConstraintOfDistributiveConditionalType(type: ConditionalType): Type {
@@ -6246,7 +6251,10 @@ namespace ts {
62466251
const constraint = getConstraintOfType(type.checkType);
62476252
if (constraint) {
62486253
const mapper = createTypeMapper([<TypeParameter>type.root.checkType], [constraint]);
6249-
return getConditionalTypeInstantiation(type, combineTypeMappers(mapper, type.mapper));
6254+
const instantiated = getConditionalTypeInstantiation(type, combineTypeMappers(mapper, type.mapper));
6255+
if (!(instantiated.flags & TypeFlags.Never)) {
6256+
return instantiated;
6257+
}
62506258
}
62516259
}
62526260
return undefined;
@@ -8398,12 +8406,6 @@ namespace ts {
83988406
return type.resolvedFalseType || (type.resolvedFalseType = instantiateType(type.root.falseType, type.mapper));
83998407
}
84008408

8401-
function getInferredTrueTypeFromConditionalType(type: ConditionalType) {
8402-
return type.combinedMapper ?
8403-
type.resolvedInferredTrueType || (type.resolvedInferredTrueType = instantiateType(type.root.trueType, type.combinedMapper)) :
8404-
getTrueTypeFromConditionalType(type);
8405-
}
8406-
84078409
function getInferTypeParameters(node: ConditionalTypeNode): TypeParameter[] {
84088410
let result: TypeParameter[];
84098411
if (node.locals) {
@@ -8416,13 +8418,25 @@ namespace ts {
84168418
return result;
84178419
}
84188420

8421+
function getTopConditionalType(node: Node): ConditionalTypeNode {
8422+
let result: ConditionalTypeNode;
8423+
while (node) {
8424+
if (node.kind === SyntaxKind.ConditionalType) {
8425+
result = <ConditionalTypeNode>node;
8426+
}
8427+
node = node.parent;
8428+
}
8429+
return result;
8430+
}
8431+
84198432
function getTypeFromConditionalTypeNode(node: ConditionalTypeNode): Type {
84208433
const links = getNodeLinks(node);
84218434
if (!links.resolvedType) {
84228435
const checkType = getTypeFromTypeNode(node.checkType);
84238436
const aliasTypeArguments = getAliasTypeArgumentsForTypeNode(node);
84248437
const allOuterTypeParameters = getOuterTypeParameters(node, /*includeThisTypes*/ true);
8425-
const outerTypeParameters = aliasTypeArguments ? allOuterTypeParameters : filter(allOuterTypeParameters, tp => isTypeParameterPossiblyReferenced(tp, node));
8438+
const topNode = getTopConditionalType(node);
8439+
const outerTypeParameters = aliasTypeArguments ? allOuterTypeParameters : filter(allOuterTypeParameters, tp => isTypeParameterPossiblyReferenced(tp, topNode));
84268440
const root: ConditionalRoot = {
84278441
node,
84288442
checkType,

src/compiler/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3878,7 +3878,7 @@ namespace ts {
38783878
resolvedTrueType?: Type;
38793879
resolvedFalseType?: Type;
38803880
/* @internal */
3881-
resolvedInferredTrueType?: Type;
3881+
resolvedDefaultConstraint?: Type;
38823882
/* @internal */
38833883
mapper?: TypeMapper;
38843884
/* @internal */

0 commit comments

Comments
 (0)