@@ -3040,7 +3040,7 @@ namespace ts {
30403040 return createConditionalTypeNode(checkTypeNode, extendsTypeNode, trueTypeNode, falseTypeNode);
30413041 }
30423042 if (type.flags & TypeFlags.Substitution) {
3043- return typeToTypeNodeHelper((<SubstitutionType>type).typeParameter , context);
3043+ return typeToTypeNodeHelper((<SubstitutionType>type).typeVariable , context);
30443044 }
30453045
30463046 Debug.fail("Should be unreachable.");
@@ -7305,7 +7305,7 @@ namespace ts {
73057305 const res = tryGetDeclaredTypeOfSymbol(symbol);
73067306 if (res) {
73077307 return checkNoTypeArguments(node, symbol) ?
7308- res.flags & TypeFlags.TypeParameter ? getConstrainedTypeParameter (<TypeParameter>res, node) : res :
7308+ res.flags & TypeFlags.TypeParameter ? getConstrainedTypeVariable (<TypeParameter>res, node) : res :
73097309 unknownType;
73107310 }
73117311
@@ -7344,25 +7344,36 @@ namespace ts {
73447344 }
73457345 }
73467346
7347- function getSubstitutionType(typeParameter: TypeParameter , substitute: Type) {
7347+ function getSubstitutionType(typeVariable: TypeVariable , substitute: Type) {
73487348 const result = <SubstitutionType>createType(TypeFlags.Substitution);
7349- result.typeParameter = typeParameter ;
7349+ result.typeVariable = typeVariable ;
73507350 result.substitute = substitute;
73517351 return result;
73527352 }
73537353
7354- function getConstrainedTypeParameter(typeParameter: TypeParameter, node: Node) {
7354+ function isUnaryTupleTypeNode(node: TypeNode) {
7355+ return node.kind === SyntaxKind.TupleType && (<TupleTypeNode>node).elementTypes.length === 1;
7356+ }
7357+
7358+ function getImpliedConstraint(typeVariable: TypeVariable, checkNode: TypeNode, extendsNode: TypeNode): Type {
7359+ return isUnaryTupleTypeNode(checkNode) && isUnaryTupleTypeNode(extendsNode) ? getImpliedConstraint(typeVariable, (<TupleTypeNode>checkNode).elementTypes[0], (<TupleTypeNode>extendsNode).elementTypes[0]) :
7360+ getActualTypeVariable(getTypeFromTypeNode(checkNode)) === typeVariable ? getTypeFromTypeNode(extendsNode) :
7361+ undefined;
7362+ }
7363+
7364+ function getConstrainedTypeVariable(typeVariable: TypeVariable, node: Node) {
73557365 let constraints: Type[];
73567366 while (isPartOfTypeNode(node)) {
73577367 const parent = node.parent;
73587368 if (parent.kind === SyntaxKind.ConditionalType && node === (<ConditionalTypeNode>parent).trueType) {
7359- if (getTypeFromTypeNode((<ConditionalTypeNode>parent).checkType) === typeParameter) {
7360- constraints = append(constraints, getTypeFromTypeNode((<ConditionalTypeNode>parent).extendsType));
7369+ const constraint = getImpliedConstraint(typeVariable, (<ConditionalTypeNode>parent).checkType, (<ConditionalTypeNode>parent).extendsType);
7370+ if (constraint) {
7371+ constraints = append(constraints, constraint);
73617372 }
73627373 }
73637374 node = parent;
73647375 }
7365- return constraints ? getSubstitutionType(typeParameter , getIntersectionType(append(constraints, typeParameter ))) : typeParameter ;
7376+ return constraints ? getSubstitutionType(typeVariable , getIntersectionType(append(constraints, typeVariable ))) : typeVariable ;
73667377 }
73677378
73687379 function isJSDocTypeReference(node: TypeReferenceType): node is TypeReferenceNode {
@@ -8258,7 +8269,13 @@ namespace ts {
82588269 function getTypeFromIndexedAccessTypeNode(node: IndexedAccessTypeNode) {
82598270 const links = getNodeLinks(node);
82608271 if (!links.resolvedType) {
8261- links.resolvedType = getIndexedAccessType(getTypeFromTypeNode(node.objectType), getTypeFromTypeNode(node.indexType), node);
8272+ const objectType = getTypeFromTypeNode(node.objectType);
8273+ const indexType = getTypeFromTypeNode(node.indexType);
8274+ const resolved = getIndexedAccessType(objectType, indexType, node);
8275+ links.resolvedType = resolved.flags & TypeFlags.IndexedAccess &&
8276+ (<IndexedAccessType>resolved).objectType === objectType &&
8277+ (<IndexedAccessType>resolved).indexType === indexType ?
8278+ getConstrainedTypeVariable(<IndexedAccessType>resolved, node) : resolved;
82628279 }
82638280 return links.resolvedType;
82648281 }
@@ -8278,8 +8295,8 @@ namespace ts {
82788295 return links.resolvedType;
82798296 }
82808297
8281- function getActualTypeParameter (type: Type) {
8282- return type.flags & TypeFlags.Substitution ? (<SubstitutionType>type).typeParameter : type;
8298+ function getActualTypeVariable (type: Type) {
8299+ return type.flags & TypeFlags.Substitution ? (<SubstitutionType>type).typeVariable : type;
82838300 }
82848301
82858302 function getConditionalType(root: ConditionalRoot, mapper: TypeMapper): Type {
@@ -8323,7 +8340,7 @@ namespace ts {
83238340 }
83248341 }
83258342 // Return a deferred type for a check that is neither definitely true nor definitely false
8326- const erasedCheckType = getActualTypeParameter (checkType);
8343+ const erasedCheckType = getActualTypeVariable (checkType);
83278344 const result = <ConditionalType>createType(TypeFlags.Conditional);
83288345 result.root = root;
83298346 result.checkType = erasedCheckType;
@@ -9043,7 +9060,7 @@ namespace ts {
90439060 return getConditionalTypeInstantiation(<ConditionalType>type, combineTypeMappers((<ConditionalType>type).mapper, mapper));
90449061 }
90459062 if (type.flags & TypeFlags.Substitution) {
9046- return mapper ((<SubstitutionType>type).typeParameter );
9063+ return instantiateType ((<SubstitutionType>type).typeVariable, mapper );
90479064 }
90489065 }
90499066 return type;
@@ -9650,10 +9667,10 @@ namespace ts {
96509667 target = (<LiteralType>target).regularType;
96519668 }
96529669 if (source.flags & TypeFlags.Substitution) {
9653- source = relation === definitelyAssignableRelation ? (<SubstitutionType>source).typeParameter : (<SubstitutionType>source).substitute;
9670+ source = relation === definitelyAssignableRelation ? (<SubstitutionType>source).typeVariable : (<SubstitutionType>source).substitute;
96549671 }
96559672 if (target.flags & TypeFlags.Substitution) {
9656- target = (<SubstitutionType>target).typeParameter ;
9673+ target = (<SubstitutionType>target).typeVariable ;
96579674 }
96589675
96599676 // both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases
0 commit comments