@@ -3021,6 +3021,11 @@ namespace ts {
3021
3021
if (type.flags & TypeFlags.Substitution) {
3022
3022
return typeToTypeNodeHelper((<SubstitutionType>type).typeParameter, context);
3023
3023
}
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
+ }
3024
3029
3025
3030
Debug.fail("Should be unreachable.");
3026
3031
@@ -3517,7 +3522,7 @@ namespace ts {
3517
3522
const params = getTypeParametersOfClassOrInterface(
3518
3523
parentSymbol.flags & SymbolFlags.Alias ? resolveAlias(parentSymbol) : parentSymbol
3519
3524
);
3520
- typeParameterNodes = mapToTypeNodes(map (params, (nextSymbol as TransientSymbol).mapper), context);
3525
+ typeParameterNodes = mapToTypeNodes(mapIndexless (params, (nextSymbol as TransientSymbol).mapper), context);
3521
3526
}
3522
3527
else {
3523
3528
typeParameterNodes = typeParametersToTypeParameterDeclarations(symbol, context);
@@ -4736,12 +4741,14 @@ namespace ts {
4736
4741
case SyntaxKind.JSDocTemplateTag:
4737
4742
case SyntaxKind.MappedType:
4738
4743
case SyntaxKind.ConditionalType:
4744
+ case SyntaxKind.CallExpression:
4745
+ case SyntaxKind.NewExpression:
4739
4746
const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes);
4740
4747
if (node.kind === SyntaxKind.MappedType) {
4741
4748
return append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode((<MappedTypeNode>node).typeParameter)));
4742
4749
}
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));
4745
4752
}
4746
4753
const outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, getEffectiveTypeParameterDeclarations(<DeclarationWithTypeParameters>node) || emptyArray);
4747
4754
const thisType = includeThisTypes &&
@@ -8334,7 +8341,7 @@ namespace ts {
8334
8341
return type.resolvedFalseType || (type.resolvedFalseType = instantiateType(type.root.falseType, type.mapper));
8335
8342
}
8336
8343
8337
- function getInferTypeParameters(node: ConditionalTypeNode): TypeParameter[] {
8344
+ function getInferTypeParameters(node: ConditionalTypeNode | CallLikeExpression ): TypeParameter[] {
8338
8345
let result: TypeParameter[];
8339
8346
if (node.locals) {
8340
8347
node.locals.forEach(symbol => {
@@ -8375,10 +8382,16 @@ namespace ts {
8375
8382
return links.resolvedType;
8376
8383
}
8377
8384
8385
+ function createInferType(target: TypeParameter): InferType {
8386
+ const type = createType(TypeFlags.InferType) as InferType;
8387
+ type.target = target;
8388
+ return type;
8389
+ }
8390
+
8378
8391
function getTypeFromInferTypeNode(node: InferTypeNode): Type {
8379
8392
const links = getNodeLinks(node);
8380
8393
if (!links.resolvedType) {
8381
- links.resolvedType = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node.typeParameter));
8394
+ links.resolvedType = createInferType( getDeclaredTypeOfTypeParameter(getSymbolOfNode(node.typeParameter) ));
8382
8395
}
8383
8396
return links.resolvedType;
8384
8397
}
@@ -8882,7 +8895,7 @@ namespace ts {
8882
8895
// mapper to the type parameters to produce the effective list of type arguments, and compute the
8883
8896
// instantiation cache key from the type IDs of the type arguments.
8884
8897
const combinedMapper = type.objectFlags & ObjectFlags.Instantiated ? combineTypeMappers(type.mapper, mapper) : mapper;
8885
- const typeArguments = map (typeParameters, combinedMapper);
8898
+ const typeArguments = mapIndexless (typeParameters, combinedMapper);
8886
8899
const id = getTypeListId(typeArguments);
8887
8900
let result = links.instantiations.get(id);
8888
8901
if (!result) {
@@ -8965,7 +8978,7 @@ namespace ts {
8965
8978
// We are instantiating a conditional type that has one or more type parameters in scope. Apply the
8966
8979
// mapper to the type parameters to produce the effective list of type arguments, and compute the
8967
8980
// 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);
8969
8982
const id = getTypeListId(typeArguments);
8970
8983
let result = root.instantiations.get(id);
8971
8984
if (!result) {
@@ -9036,6 +9049,9 @@ namespace ts {
9036
9049
if (type.flags & TypeFlags.Substitution) {
9037
9050
return mapper((<SubstitutionType>type).typeParameter);
9038
9051
}
9052
+ if (type.flags & TypeFlags.InferType) {
9053
+ return mapper((<InferType>type).target, /*isInferDeclaration*/ true);
9054
+ }
9039
9055
}
9040
9056
return type;
9041
9057
}
@@ -9642,9 +9658,15 @@ namespace ts {
9642
9658
if (source.flags & TypeFlags.Substitution) {
9643
9659
source = relation === definitelyAssignableRelation ? (<SubstitutionType>source).typeParameter : (<SubstitutionType>source).substitute;
9644
9660
}
9661
+ if (source.flags & TypeFlags.InferType) {
9662
+ source = (<InferType>source).target;
9663
+ }
9645
9664
if (target.flags & TypeFlags.Substitution) {
9646
9665
target = (<SubstitutionType>target).typeParameter;
9647
9666
}
9667
+ if (target.flags & TypeFlags.InferType) {
9668
+ target = (<InferType>target).target;
9669
+ }
9648
9670
9649
9671
// both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases
9650
9672
if (source === target) return Ternary.True;
@@ -11587,6 +11609,12 @@ namespace ts {
11587
11609
if (!couldContainTypeVariables(target)) {
11588
11610
return;
11589
11611
}
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
+ }
11590
11618
if (source.flags & TypeFlags.Any) {
11591
11619
// We are inferring from an 'any' type. We want to infer this type for every type parameter
11592
11620
// referenced in the target type, so we record it as the propagation type and infer from the
@@ -17529,10 +17557,29 @@ namespace ts {
17529
17557
candidate = originalCandidate;
17530
17558
if (candidate.typeParameters) {
17531
17559
let typeArgumentTypes: Type[];
17560
+ const isJavascript = isInJavaScriptFile(candidate.declaration);
17532
17561
if (typeArguments) {
17533
17562
const typeArgumentResult = checkTypeArguments(candidate, typeArguments, /*reportErrors*/ false);
17534
17563
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
+ }
17536
17583
}
17537
17584
else {
17538
17585
candidateForTypeArgumentError = originalCandidate;
@@ -17542,7 +17589,6 @@ namespace ts {
17542
17589
else {
17543
17590
typeArgumentTypes = inferTypeArguments(node, candidate, args, excludeArgument, inferenceContext);
17544
17591
}
17545
- const isJavascript = isInJavaScriptFile(candidate.declaration);
17546
17592
candidate = getSignatureInstantiation(candidate, typeArgumentTypes, isJavascript);
17547
17593
}
17548
17594
if (!checkApplicableSignature(node, args, candidate, relation, excludeArgument, /*reportErrors*/ false)) {
@@ -20544,9 +20590,18 @@ namespace ts {
20544
20590
forEachChild(node, checkSourceElement);
20545
20591
}
20546
20592
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
+
20547
20602
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 );
20550
20605
}
20551
20606
checkSourceElement(node.typeParameter);
20552
20607
}
0 commit comments