@@ -12386,22 +12386,7 @@ namespace ts {
12386
12386
callback(getTypeAtPosition(source, i), getTypeAtPosition(target, i));
12387
12387
}
12388
12388
if (targetRestTypeVariable) {
12389
- const sourceRestTypeVariable = getRestTypeParameter(source);
12390
- if (sourceRestTypeVariable && paramCount === sourceCount - 1) {
12391
- callback(sourceRestTypeVariable, targetRestTypeVariable);
12392
- }
12393
- else {
12394
- const types = [];
12395
- const names = [];
12396
- for (let i = paramCount; i < maxCount; i++) {
12397
- types.push(getTypeAtPosition(source, i));
12398
- names.push(getParameterNameAtPosition(source, i));
12399
- }
12400
- const minArgumentCount = getMinArgumentCount(source);
12401
- const minLength = minArgumentCount < paramCount ? 0 : minArgumentCount - paramCount;
12402
- const rest = createTupleType(types, minLength, sourceHasRest, names);
12403
- callback(rest, targetRestTypeVariable);
12404
- }
12389
+ callback(getRestTypeAtPosition(source, paramCount), targetRestTypeVariable);
12405
12390
}
12406
12391
}
12407
12392
@@ -15203,43 +15188,35 @@ namespace ts {
15203
15188
}
15204
15189
const iife = getImmediatelyInvokedFunctionExpression(func);
15205
15190
if (iife && iife.arguments) {
15191
+ const args = getEffectiveCallArguments(iife)!;
15206
15192
const indexOfParameter = func.parameters.indexOf(parameter);
15207
15193
if (parameter.dotDotDotToken) {
15208
- const restTypes: Type[] = [];
15209
- for (let i = indexOfParameter; i < iife.arguments.length; i++) {
15210
- restTypes.push(getWidenedLiteralType(checkExpression(iife.arguments[i])));
15211
- }
15212
- return restTypes.length ? createArrayType(getUnionType(restTypes)) : undefined;
15194
+ return getSpreadArgumentType(iife, args, indexOfParameter, args.length, anyType, /*context*/ undefined);
15213
15195
}
15214
15196
const links = getNodeLinks(iife);
15215
15197
const cached = links.resolvedSignature;
15216
15198
links.resolvedSignature = anySignature;
15217
- const type = indexOfParameter < iife.arguments .length ?
15218
- getWidenedLiteralType(checkExpression(iife.arguments [indexOfParameter])) :
15199
+ const type = indexOfParameter < args .length ?
15200
+ getWidenedLiteralType(checkExpression(args [indexOfParameter])) :
15219
15201
parameter.initializer ? undefined : undefinedWideningType;
15220
15202
links.resolvedSignature = cached;
15221
15203
return type;
15222
15204
}
15223
15205
const contextualSignature = getContextualSignature(func);
15224
15206
if (contextualSignature) {
15225
- const funcHasRestParameters = hasRestParameter(func);
15226
- const len = func.parameters.length - (funcHasRestParameters ? 1 : 0);
15207
+ const funcHasRestParameter = hasRestParameter(func);
15208
+ const len = func.parameters.length - (funcHasRestParameter ? 1 : 0);
15227
15209
let indexOfParameter = func.parameters.indexOf(parameter);
15228
15210
if (getThisParameter(func) !== undefined && !contextualSignature.thisParameter) {
15229
15211
Debug.assert(indexOfParameter !== 0); // Otherwise we should not have called `getContextuallyTypedParameterType`.
15230
15212
indexOfParameter -= 1;
15231
15213
}
15232
-
15233
15214
if (indexOfParameter < len) {
15234
15215
return getTypeAtPosition(contextualSignature, indexOfParameter);
15235
15216
}
15236
-
15237
15217
// If last parameter is contextually rest parameter get its type
15238
- if (funcHasRestParameters &&
15239
- indexOfParameter === func.parameters.length - 1 &&
15240
- hasEffectiveRestParameter(contextualSignature) &&
15241
- func.parameters.length >= contextualSignature.parameters.length) {
15242
- return getTypeOfRestParameter(contextualSignature);
15218
+ if (funcHasRestParameter && indexOfParameter === len) {
15219
+ return getRestTypeAtPosition(contextualSignature, indexOfParameter);
15243
15220
}
15244
15221
}
15245
15222
}
@@ -17806,7 +17783,7 @@ namespace ts {
17806
17783
}
17807
17784
}
17808
17785
17809
- function isSpreadArgument(arg: Expression | undefined) {
17786
+ function isSpreadArgument(arg: Expression | undefined): arg is Expression {
17810
17787
return !!arg && (arg.kind === SyntaxKind.SpreadElement || arg.kind === SyntaxKind.SyntheticExpression && (<SyntheticExpression>arg).isSpread);
17811
17788
}
17812
17789
@@ -18028,12 +18005,14 @@ namespace ts {
18028
18005
}
18029
18006
18030
18007
function getSpreadArgumentType(node: CallLikeExpression, args: ReadonlyArray<Expression>, index: number, argCount: number, restType: TypeParameter, context: InferenceContext | undefined) {
18031
- if (index == = argCount - 1) {
18032
- const arg = getEffectiveArgument(node, args, index );
18008
+ if (index > = argCount - 1) {
18009
+ const arg = getEffectiveArgument(node, args, argCount - 1 );
18033
18010
if (isSpreadArgument(arg)) {
18034
18011
// We are inferring from a spread expression in the last argument position, i.e. both the parameter
18035
18012
// and the argument are ...x forms.
18036
- return checkExpressionWithContextualType((<SpreadElement>arg).expression, restType, context);
18013
+ return arg.kind === SyntaxKind.SyntheticExpression ?
18014
+ createArrayType((<SyntheticExpression>arg).type) :
18015
+ checkExpressionWithContextualType((<SpreadElement>arg).expression, restType, context);
18037
18016
}
18038
18017
}
18039
18018
const contextualType = getIndexTypeOfType(restType, IndexKind.Number) || anyType;
@@ -19560,6 +19539,27 @@ namespace ts {
19560
19539
return anyType;
19561
19540
}
19562
19541
19542
+ function getRestTypeAtPosition(source: Signature, pos: number): Type {
19543
+ const paramCount = getParameterCount(source);
19544
+ const hasRest = hasEffectiveRestParameter(source);
19545
+ if (hasRest && pos === paramCount - 1) {
19546
+ const restTypeVariable = getRestTypeParameter(source);
19547
+ if (restTypeVariable) {
19548
+ return restTypeVariable;
19549
+ }
19550
+ }
19551
+ const start = hasRest ? Math.min(pos, paramCount - 1) : pos;
19552
+ const types = [];
19553
+ const names = [];
19554
+ for (let i = start; i < paramCount; i++) {
19555
+ types.push(getTypeAtPosition(source, i));
19556
+ names.push(getParameterNameAtPosition(source, i));
19557
+ }
19558
+ const minArgumentCount = getMinArgumentCount(source);
19559
+ const minLength = minArgumentCount < start ? 0 : minArgumentCount - start;
19560
+ return createTupleType(types, minLength, hasRest, names);
19561
+ }
19562
+
19563
19563
function getTypeOfRestParameter(signature: Signature) {
19564
19564
if (signature.hasRestParameter) {
19565
19565
const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
@@ -19653,11 +19653,11 @@ namespace ts {
19653
19653
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType);
19654
19654
}
19655
19655
}
19656
- if (signature.hasRestParameter && context.hasRestParameter && signature.parameters.length >= context.parameters.length ) {
19656
+ if (signature.hasRestParameter) {
19657
19657
// parameter might be a transient symbol generated by use of `arguments` in the function body.
19658
19658
const parameter = last(signature.parameters);
19659
19659
if (isTransientSymbol(parameter) || !getEffectiveTypeAnnotationNode(<ParameterDeclaration>parameter.valueDeclaration)) {
19660
- const contextualParameterType = getTypeOfSymbol(last( context.parameters) );
19660
+ const contextualParameterType = getRestTypeAtPosition( context, len );
19661
19661
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType);
19662
19662
}
19663
19663
}
0 commit comments