@@ -3021,6 +3021,11 @@ namespace ts {
30213021 if (type.flags & TypeFlags.Substitution) {
30223022 return typeToTypeNodeHelper((<SubstitutionType>type).typeParameter, context);
30233023 }
3024+ if (type.flags & TypeFlags.InferType) {
3025+ // Infer types only parse as identifiers, so the target should always be a TypeParameter that becomes a TypeReferenceNode
3026+ const ref = typeToTypeNodeHelper((<InferType>type).target, context) as TypeReferenceNode;
3027+ return createInferTypeNode(createTypeParameterDeclaration(ref.typeName as Identifier));
3028+ }
30243029
30253030 Debug.fail("Should be unreachable.");
30263031
@@ -3517,7 +3522,7 @@ namespace ts {
35173522 const params = getTypeParametersOfClassOrInterface(
35183523 parentSymbol.flags & SymbolFlags.Alias ? resolveAlias(parentSymbol) : parentSymbol
35193524 );
3520- typeParameterNodes = mapToTypeNodes(map (params, (nextSymbol as TransientSymbol).mapper), context);
3525+ typeParameterNodes = mapToTypeNodes(mapIndexless (params, (nextSymbol as TransientSymbol).mapper), context);
35213526 }
35223527 else {
35233528 typeParameterNodes = typeParametersToTypeParameterDeclarations(symbol, context);
@@ -4736,12 +4741,14 @@ namespace ts {
47364741 case SyntaxKind.JSDocTemplateTag:
47374742 case SyntaxKind.MappedType:
47384743 case SyntaxKind.ConditionalType:
4744+ case SyntaxKind.CallExpression:
4745+ case SyntaxKind.NewExpression:
47394746 const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes);
47404747 if (node.kind === SyntaxKind.MappedType) {
47414748 return append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode((<MappedTypeNode>node).typeParameter)));
47424749 }
4743- else if (node.kind === SyntaxKind.ConditionalType) {
4744- return concatenate(outerTypeParameters, getInferTypeParameters(<ConditionalTypeNode>node));
4750+ else if (node.kind === SyntaxKind.ConditionalType || node.kind === SyntaxKind.NewExpression || node.kind === SyntaxKind.CallExpression ) {
4751+ return concatenate(outerTypeParameters, getInferTypeParameters(<ConditionalTypeNode | CallLikeExpression >node));
47454752 }
47464753 const outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, getEffectiveTypeParameterDeclarations(<DeclarationWithTypeParameters>node) || emptyArray);
47474754 const thisType = includeThisTypes &&
@@ -8334,7 +8341,7 @@ namespace ts {
83348341 return type.resolvedFalseType || (type.resolvedFalseType = instantiateType(type.root.falseType, type.mapper));
83358342 }
83368343
8337- function getInferTypeParameters(node: ConditionalTypeNode): TypeParameter[] {
8344+ function getInferTypeParameters(node: ConditionalTypeNode | CallLikeExpression ): TypeParameter[] {
83388345 let result: TypeParameter[];
83398346 if (node.locals) {
83408347 node.locals.forEach(symbol => {
@@ -8375,10 +8382,16 @@ namespace ts {
83758382 return links.resolvedType;
83768383 }
83778384
8385+ function createInferType(target: TypeParameter): InferType {
8386+ const type = createType(TypeFlags.InferType) as InferType;
8387+ type.target = target;
8388+ return type;
8389+ }
8390+
83788391 function getTypeFromInferTypeNode(node: InferTypeNode): Type {
83798392 const links = getNodeLinks(node);
83808393 if (!links.resolvedType) {
8381- links.resolvedType = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node.typeParameter));
8394+ links.resolvedType = createInferType( getDeclaredTypeOfTypeParameter(getSymbolOfNode(node.typeParameter) ));
83828395 }
83838396 return links.resolvedType;
83848397 }
@@ -8882,7 +8895,7 @@ namespace ts {
88828895 // mapper to the type parameters to produce the effective list of type arguments, and compute the
88838896 // instantiation cache key from the type IDs of the type arguments.
88848897 const combinedMapper = type.objectFlags & ObjectFlags.Instantiated ? combineTypeMappers(type.mapper, mapper) : mapper;
8885- const typeArguments = map (typeParameters, combinedMapper);
8898+ const typeArguments = mapIndexless (typeParameters, combinedMapper);
88868899 const id = getTypeListId(typeArguments);
88878900 let result = links.instantiations.get(id);
88888901 if (!result) {
@@ -8965,7 +8978,7 @@ namespace ts {
89658978 // We are instantiating a conditional type that has one or more type parameters in scope. Apply the
89668979 // mapper to the type parameters to produce the effective list of type arguments, and compute the
89678980 // instantiation cache key from the type IDs of the type arguments.
8968- const typeArguments = map (root.outerTypeParameters, mapper);
8981+ const typeArguments = mapIndexless (root.outerTypeParameters, mapper);
89698982 const id = getTypeListId(typeArguments);
89708983 let result = root.instantiations.get(id);
89718984 if (!result) {
@@ -9036,6 +9049,9 @@ namespace ts {
90369049 if (type.flags & TypeFlags.Substitution) {
90379050 return mapper((<SubstitutionType>type).typeParameter);
90389051 }
9052+ if (type.flags & TypeFlags.InferType) {
9053+ return mapper((<InferType>type).target, /*isInferDeclaration*/ true);
9054+ }
90399055 }
90409056 return type;
90419057 }
@@ -9642,9 +9658,15 @@ namespace ts {
96429658 if (source.flags & TypeFlags.Substitution) {
96439659 source = relation === definitelyAssignableRelation ? (<SubstitutionType>source).typeParameter : (<SubstitutionType>source).substitute;
96449660 }
9661+ if (source.flags & TypeFlags.InferType) {
9662+ source = (<InferType>source).target;
9663+ }
96459664 if (target.flags & TypeFlags.Substitution) {
96469665 target = (<SubstitutionType>target).typeParameter;
96479666 }
9667+ if (target.flags & TypeFlags.InferType) {
9668+ target = (<InferType>target).target;
9669+ }
96489670
96499671 // both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases
96509672 if (source === target) return Ternary.True;
@@ -11587,6 +11609,12 @@ namespace ts {
1158711609 if (!couldContainTypeVariables(target)) {
1158811610 return;
1158911611 }
11612+ if (source.flags & TypeFlags.InferType) {
11613+ source = (source as InferType).target;
11614+ }
11615+ if (target.flags & TypeFlags.InferType) {
11616+ target = (target as InferType).target;
11617+ }
1159011618 if (source.flags & TypeFlags.Any) {
1159111619 // We are inferring from an 'any' type. We want to infer this type for every type parameter
1159211620 // referenced in the target type, so we record it as the propagation type and infer from the
@@ -17529,10 +17557,29 @@ namespace ts {
1752917557 candidate = originalCandidate;
1753017558 if (candidate.typeParameters) {
1753117559 let typeArgumentTypes: Type[];
17560+ const isJavascript = isInJavaScriptFile(candidate.declaration);
1753217561 if (typeArguments) {
1753317562 const typeArgumentResult = checkTypeArguments(candidate, typeArguments, /*reportErrors*/ false);
1753417563 if (typeArgumentResult) {
17535- typeArgumentTypes = typeArgumentResult;
17564+ if (node.locals) {
17565+ // Call has `infer` arguments that still need to be inferred and instantiated
17566+ const inferParams = getInferTypeParameters(node);
17567+ // Mapper replaces references to infered type parameters with emptyObjectType
17568+ // Causing the original location to be the _only_ inference site
17569+ const preprocessMapper = (p: TypeParameter, isInferDecl: boolean) => {
17570+ if (!isInferDecl && contains(inferParams, p)) return emptyObjectType;
17571+ return p;
17572+ };
17573+ const resultsWithNonInferInferredVarsDefaulted = map(typeArgumentResult, t => instantiateType(t, preprocessMapper));
17574+ const partialCandidate = getSignatureInstantiation(candidate, resultsWithNonInferInferredVarsDefaulted, isJavascript);
17575+ const context = createInferenceContext(inferParams, partialCandidate, InferenceFlags.None);
17576+ const inferences = inferTypeArguments(node, partialCandidate, args, excludeArgument, context);
17577+ const mapper = createTypeMapper(inferParams, inferences);
17578+ typeArgumentTypes = map(typeArgumentResult, t => instantiateType(t, mapper));
17579+ }
17580+ else {
17581+ typeArgumentTypes = typeArgumentResult;
17582+ }
1753617583 }
1753717584 else {
1753817585 candidateForTypeArgumentError = originalCandidate;
@@ -17542,7 +17589,6 @@ namespace ts {
1754217589 else {
1754317590 typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext);
1754417591 }
17545- const isJavascript = isInJavaScriptFile(candidate.declaration);
1754617592 candidate = getSignatureInstantiation(candidate, typeArgumentTypes, isJavascript);
1754717593 }
1754817594 if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) {
@@ -20544,9 +20590,18 @@ namespace ts {
2054420590 forEachChild(node, checkSourceElement);
2054520591 }
2054620592
20593+ function isConditionalTypeExtendsClause(n: Node) {
20594+ return n.parent && n.parent.kind === SyntaxKind.ConditionalType && (<ConditionalTypeNode>n.parent).extendsType === n;
20595+ }
20596+
20597+ function isCallOrNewExpressionTypeArgument(n: Node) {
20598+ return n.parent && (n.parent.kind === SyntaxKind.CallExpression || n.parent.kind === SyntaxKind.NewExpression)
20599+ && contains((<CallExpression | NewExpression>n.parent).typeArguments, n);
20600+ }
20601+
2054720602 function checkInferType(node: InferTypeNode) {
20548- if (!findAncestor(node, n => n.parent && n.parent.kind === SyntaxKind.ConditionalType && (<ConditionalTypeNode>n.parent).extendsType === n )) {
20549- grammarErrorOnNode(node, Diagnostics.infer_declarations_are_only_permitted_in_the_extends_clause_of_a_conditional_type );
20603+ if (!findAncestor(node, n => isConditionalTypeExtendsClause(n) || isCallOrNewExpressionTypeArgument(n) )) {
20604+ grammarErrorOnNode(node, Diagnostics.infer_declarations_are_only_permitted_in_the_extends_clause_of_a_conditional_type_or_in_call_or_new_expression_type_argument_lists );
2055020605 }
2055120606 checkSourceElement(node.typeParameter);
2055220607 }
0 commit comments