@@ -7789,8 +7789,12 @@ namespace ts {
7789
7789
}
7790
7790
7791
7791
function tryGetRestTypeOfSignature(signature: Signature): Type | undefined {
7792
- const type = getTypeOfRestParameter(signature);
7793
- return type && getIndexTypeOfType(type, IndexKind.Number);
7792
+ if (signature.hasRestParameter) {
7793
+ const sigRestType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
7794
+ const restType = isTupleType(sigRestType) ? getRestTypeOfTupleType(sigRestType) : sigRestType;
7795
+ return restType && getIndexTypeOfType(restType, IndexKind.Number);
7796
+ }
7797
+ return undefined;
7794
7798
}
7795
7799
7796
7800
function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean): Signature {
@@ -10718,9 +10722,9 @@ namespace ts {
10718
10722
}
10719
10723
10720
10724
const sourceCount = getParameterCount(source);
10721
- const sourceGenericRestType = getGenericRestType (source);
10722
- const targetGenericRestType = sourceGenericRestType ? getGenericRestType (target) : undefined;
10723
- if (sourceGenericRestType && !(targetGenericRestType && sourceCount === targetCount)) {
10725
+ const sourceRestType = getNonArrayRestType (source);
10726
+ const targetRestType = sourceRestType ? getNonArrayRestType (target) : undefined;
10727
+ if (sourceRestType && !(targetRestType && sourceCount === targetCount)) {
10724
10728
return Ternary.False;
10725
10729
}
10726
10730
@@ -10749,8 +10753,8 @@ namespace ts {
10749
10753
const paramCount = Math.max(sourceCount, targetCount);
10750
10754
const lastIndex = paramCount - 1;
10751
10755
for (let i = 0; i < paramCount; i++) {
10752
- const sourceType = i === lastIndex && sourceGenericRestType || getTypeAtPosition(source, i);
10753
- const targetType = i === lastIndex && targetGenericRestType || getTypeAtPosition(target, i);
10756
+ const sourceType = i === lastIndex && sourceRestType || getTypeAtPosition(source, i);
10757
+ const targetType = i === lastIndex && targetRestType || getTypeAtPosition(target, i);
10754
10758
// In order to ensure that any generic type Foo<T> is at least co-variant with respect to T no matter
10755
10759
// how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions,
10756
10760
// they naturally relate only contra-variantly). However, if the source and target parameters both have
@@ -12693,6 +12697,11 @@ namespace ts {
12693
12697
return type.target.hasRestElement ? type.typeArguments![type.target.typeParameters!.length - 1] : undefined;
12694
12698
}
12695
12699
12700
+ function getRestArrayTypeOfTupleType(type: TupleTypeReference) {
12701
+ const restType = getRestTypeOfTupleType(type);
12702
+ return restType && createArrayType(restType);
12703
+ }
12704
+
12696
12705
function getLengthOfTupleType(type: TupleTypeReference) {
12697
12706
return getTypeReferenceArity(type) - (type.target.hasRestElement ? 1 : 0);
12698
12707
}
@@ -13038,19 +13047,18 @@ namespace ts {
13038
13047
function forEachMatchingParameterType(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) {
13039
13048
const sourceCount = getParameterCount(source);
13040
13049
const targetCount = getParameterCount(target);
13041
- const sourceHasRest = hasEffectiveRestParameter (source);
13042
- const targetHasRest = hasEffectiveRestParameter (target);
13043
- const maxCount = sourceHasRest && targetHasRest ? Math.max(sourceCount, targetCount) :
13044
- sourceHasRest ? targetCount :
13045
- targetHasRest ? sourceCount :
13050
+ const sourceRestType = getEffectiveRestType (source);
13051
+ const targetRestType = getEffectiveRestType (target);
13052
+ const maxCount = sourceRestType && targetRestType ? Math.max(sourceCount, targetCount) :
13053
+ sourceRestType ? targetCount :
13054
+ targetRestType ? sourceCount :
13046
13055
Math.min(sourceCount, targetCount);
13047
- const targetGenericRestType = getGenericRestType(target);
13048
- const paramCount = targetGenericRestType ? Math.min(targetCount - 1, maxCount) : maxCount;
13056
+ const paramCount = targetRestType ? Math.min(targetCount - 1, maxCount) : maxCount;
13049
13057
for (let i = 0; i < paramCount; i++) {
13050
13058
callback(getTypeAtPosition(source, i), getTypeAtPosition(target, i));
13051
13059
}
13052
- if (targetGenericRestType ) {
13053
- callback(getRestTypeAtPosition(source, paramCount), targetGenericRestType );
13060
+ if (targetRestType ) {
13061
+ callback(getRestTypeAtPosition(source, paramCount), targetRestType );
13054
13062
}
13055
13063
}
13056
13064
@@ -13510,32 +13518,37 @@ namespace ts {
13510
13518
}
13511
13519
13512
13520
function inferFromProperties(source: Type, target: Type) {
13513
- if (isTupleType(source) && isTupleType(target)) {
13514
- const sourceLength = getLengthOfTupleType(source);
13515
- const targetLength = getLengthOfTupleType(target);
13516
- const sourceRestType = getRestTypeOfTupleType(source);
13517
- const targetRestType = getRestTypeOfTupleType(target);
13518
- const fixedLength = targetLength < sourceLength || sourceRestType ? targetLength : sourceLength;
13519
- for (let i = 0; i < fixedLength; i++) {
13520
- inferFromTypes(i < sourceLength ? source.typeArguments![i] : sourceRestType!, target.typeArguments![i]);
13521
- }
13522
- if (targetRestType) {
13523
- const types = fixedLength < sourceLength ? source.typeArguments!.slice(fixedLength, sourceLength) : [];
13524
- if (sourceRestType) {
13525
- types.push(sourceRestType);
13526
- }
13527
- if (types.length) {
13528
- inferFromTypes(getUnionType(types), targetRestType);
13521
+ if (isTupleType(source)) {
13522
+ if (isTupleType(target)) {
13523
+ const sourceLength = getLengthOfTupleType(source);
13524
+ const targetLength = getLengthOfTupleType(target);
13525
+ const sourceRestType = getRestTypeOfTupleType(source);
13526
+ const targetRestType = getRestTypeOfTupleType(target);
13527
+ const fixedLength = targetLength < sourceLength || sourceRestType ? targetLength : sourceLength;
13528
+ for (let i = 0; i < fixedLength; i++) {
13529
+ inferFromTypes(i < sourceLength ? source.typeArguments![i] : sourceRestType!, target.typeArguments![i]);
13530
+ }
13531
+ if (targetRestType) {
13532
+ const types = fixedLength < sourceLength ? source.typeArguments!.slice(fixedLength, sourceLength) : [];
13533
+ if (sourceRestType) {
13534
+ types.push(sourceRestType);
13535
+ }
13536
+ if (types.length) {
13537
+ inferFromTypes(getUnionType(types), targetRestType);
13538
+ }
13529
13539
}
13540
+ return;
13541
+ }
13542
+ if (isArrayType(target)) {
13543
+ inferFromIndexTypes(source, target);
13544
+ return;
13530
13545
}
13531
13546
}
13532
- else {
13533
- const properties = getPropertiesOfObjectType(target);
13534
- for (const targetProp of properties) {
13535
- const sourceProp = getPropertyOfType(source, targetProp.escapedName);
13536
- if (sourceProp) {
13537
- inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
13538
- }
13547
+ const properties = getPropertiesOfObjectType(target);
13548
+ for (const targetProp of properties) {
13549
+ const sourceProp = getPropertyOfType(source, targetProp.escapedName);
13550
+ if (sourceProp) {
13551
+ inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
13539
13552
}
13540
13553
}
13541
13554
}
@@ -18679,8 +18692,8 @@ namespace ts {
18679
18692
inferTypes(context.inferences, thisArgumentType, thisType);
18680
18693
}
18681
18694
18682
- const genericRestType = getGenericRestType (signature);
18683
- const argCount = genericRestType ? Math.min(getParameterCount(signature) - 1, args.length) : args.length;
18695
+ const restType = getNonArrayRestType (signature);
18696
+ const argCount = restType ? Math.min(getParameterCount(signature) - 1, args.length) : args.length;
18684
18697
for (let i = 0; i < argCount; i++) {
18685
18698
const arg = args[i];
18686
18699
if (arg.kind !== SyntaxKind.OmittedExpression) {
@@ -18693,14 +18706,21 @@ namespace ts {
18693
18706
}
18694
18707
}
18695
18708
18696
- if (genericRestType ) {
18697
- const spreadType = getSpreadArgumentType(args, argCount, args.length, genericRestType , context);
18698
- inferTypes(context.inferences, spreadType, genericRestType );
18709
+ if (restType ) {
18710
+ const spreadType = getSpreadArgumentType(args, argCount, args.length, restType , context);
18711
+ inferTypes(context.inferences, spreadType, restType );
18699
18712
}
18700
18713
18701
18714
return getInferredTypes(context);
18702
18715
}
18703
18716
18717
+ function getArrayifiedType(type: Type) {
18718
+ if (forEachType(type, t => !(t.flags & (TypeFlags.Any | TypeFlags.Instantiable) || isArrayType(t) || isTupleType(t)))) {
18719
+ return createArrayType(getIndexTypeOfType(type, IndexKind.Number) || errorType);
18720
+ }
18721
+ return type;
18722
+ }
18723
+
18704
18724
function getSpreadArgumentType(args: ReadonlyArray<Expression>, index: number, argCount: number, restType: TypeParameter, context: InferenceContext | undefined) {
18705
18725
if (index >= argCount - 1) {
18706
18726
const arg = args[argCount - 1];
@@ -18709,7 +18729,7 @@ namespace ts {
18709
18729
// and the argument are ...x forms.
18710
18730
return arg.kind === SyntaxKind.SyntheticExpression ?
18711
18731
createArrayType((<SyntheticExpression>arg).type) :
18712
- checkExpressionWithContextualType((<SpreadElement>arg).expression, restType, context);
18732
+ getArrayifiedType( checkExpressionWithContextualType((<SpreadElement>arg).expression, restType, context) );
18713
18733
}
18714
18734
}
18715
18735
const contextualType = getIndexTypeOfType(restType, IndexKind.Number) || anyType;
@@ -18814,28 +18834,27 @@ namespace ts {
18814
18834
}
18815
18835
}
18816
18836
const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1;
18817
- const restIndex = signature.hasRestParameter ? signature.parameters.length - 1 : -1 ;
18818
- const restType = restIndex >= 0 ? getTypeOfSymbol( signature.parameters[restIndex] ) : anyType ;
18819
- for (let i = 0; i < args.length ; i++) {
18837
+ const restType = getNonArrayRestType( signature) ;
18838
+ const argCount = restType ? Math.min(getParameterCount( signature) - 1, args.length ) : args.length ;
18839
+ for (let i = 0; i < argCount ; i++) {
18820
18840
const arg = args[i];
18821
18841
if (arg.kind !== SyntaxKind.OmittedExpression) {
18822
- if (i === restIndex && (restType.flags & TypeFlags.TypeParameter || isSpreadArgument(arg) && !isArrayType(restType))) {
18823
- const spreadType = getSpreadArgumentType(args, i, args.length, restType, /*context*/ undefined);
18824
- return checkTypeRelatedTo(spreadType, restType, relation, arg, headMessage);
18825
- }
18826
- else {
18827
- const paramType = getTypeAtPosition(signature, i);
18828
- const argType = checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
18829
- // If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter),
18830
- // we obtain the regular type of any object literal arguments because we may not have inferred complete
18831
- // parameter types yet and therefore excess property checks may yield false positives (see #17041).
18832
- const checkArgType = excludeArgument ? getRegularTypeOfObjectLiteral(argType) : argType;
18833
- if (!checkTypeRelatedTo(checkArgType, paramType, relation, reportErrors ? arg : undefined, headMessage)) {
18834
- return false;
18835
- }
18842
+ const paramType = getTypeAtPosition(signature, i);
18843
+ const argType = checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
18844
+ // If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter),
18845
+ // we obtain the regular type of any object literal arguments because we may not have inferred complete
18846
+ // parameter types yet and therefore excess property checks may yield false positives (see #17041).
18847
+ const checkArgType = excludeArgument ? getRegularTypeOfObjectLiteral(argType) : argType;
18848
+ if (!checkTypeRelatedTo(checkArgType, paramType, relation, reportErrors ? arg : undefined, headMessage)) {
18849
+ return false;
18836
18850
}
18837
18851
}
18838
18852
}
18853
+ if (restType) {
18854
+ const spreadType = getSpreadArgumentType(args, argCount, args.length, restType, /*context*/ undefined);
18855
+ const errorNode = reportErrors ? argCount < args.length ? args[argCount] : node : undefined;
18856
+ return checkTypeRelatedTo(spreadType, restType, relation, errorNode, headMessage);
18857
+ }
18839
18858
return true;
18840
18859
}
18841
18860
@@ -19187,7 +19206,7 @@ namespace ts {
19187
19206
checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJavaScriptFile(candidate.declaration));
19188
19207
// If the original signature has a generic rest type, instantiation may produce a
19189
19208
// signature with different arity and we need to perform another arity check.
19190
- if (getGenericRestType (candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) {
19209
+ if (getNonArrayRestType (candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) {
19191
19210
candidateForArgumentArityError = checkCandidate;
19192
19211
continue;
19193
19212
}
@@ -20138,14 +20157,11 @@ namespace ts {
20138
20157
20139
20158
function getRestTypeAtPosition(source: Signature, pos: number): Type {
20140
20159
const paramCount = getParameterCount(source);
20141
- const hasRest = hasEffectiveRestParameter(source);
20142
- if (hasRest && pos === paramCount - 1) {
20143
- const genericRestType = getGenericRestType(source);
20144
- if (genericRestType) {
20145
- return genericRestType;
20146
- }
20160
+ const restType = getEffectiveRestType(source);
20161
+ if (restType && pos === paramCount - 1) {
20162
+ return restType;
20147
20163
}
20148
- const start = hasRest ? Math.min(pos, paramCount - 1) : pos;
20164
+ const start = restType ? Math.min(pos, paramCount - 1) : pos;
20149
20165
const types = [];
20150
20166
const names = [];
20151
20167
for (let i = start; i < paramCount; i++) {
@@ -20154,18 +20170,7 @@ namespace ts {
20154
20170
}
20155
20171
const minArgumentCount = getMinArgumentCount(source);
20156
20172
const minLength = minArgumentCount < start ? 0 : minArgumentCount - start;
20157
- return createTupleType(types, minLength, hasRest, names);
20158
- }
20159
-
20160
- function getTypeOfRestParameter(signature: Signature) {
20161
- if (signature.hasRestParameter) {
20162
- const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
20163
- if (isTupleType(restType)) {
20164
- return getRestTypeOfTupleType(restType);
20165
- }
20166
- return restType;
20167
- }
20168
- return undefined;
20173
+ return createTupleType(types, minLength, !!restType, names);
20169
20174
}
20170
20175
20171
20176
function getParameterCount(signature: Signature) {
@@ -20192,22 +20197,25 @@ namespace ts {
20192
20197
return signature.minArgumentCount;
20193
20198
}
20194
20199
20195
- function getGenericRestType (signature: Signature) {
20200
+ function hasEffectiveRestParameter (signature: Signature) {
20196
20201
if (signature.hasRestParameter) {
20197
20202
const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
20198
- if (restType.flags & TypeFlags.Instantiable) {
20199
- return restType;
20200
- }
20203
+ return !isTupleType(restType) || restType.target.hasRestElement;
20201
20204
}
20202
- return undefined ;
20205
+ return false ;
20203
20206
}
20204
20207
20205
- function hasEffectiveRestParameter (signature: Signature) {
20208
+ function getEffectiveRestType (signature: Signature) {
20206
20209
if (signature.hasRestParameter) {
20207
20210
const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
20208
- return ! isTupleType(restType) || restType.target.hasRestElement ;
20211
+ return isTupleType(restType) ? getRestArrayTypeOfTupleType( restType) : restType ;
20209
20212
}
20210
- return false;
20213
+ return undefined;
20214
+ }
20215
+
20216
+ function getNonArrayRestType(signature: Signature) {
20217
+ const restType = getEffectiveRestType(signature);
20218
+ return restType && !isArrayType(restType) && !isTypeAny(restType) ? restType : undefined;
20211
20219
}
20212
20220
20213
20221
function getTypeOfFirstParameterOfSignature(signature: Signature) {
@@ -21889,10 +21897,6 @@ namespace ts {
21889
21897
}
21890
21898
}
21891
21899
21892
- function isRestParameterType(type: Type) {
21893
- return isArrayType(type) || isTupleType(type) || type.flags & TypeFlags.Instantiable && isTypeAssignableTo(type, anyArrayType);
21894
- }
21895
-
21896
21900
function checkParameter(node: ParameterDeclaration) {
21897
21901
// Grammar checking
21898
21902
// It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the
@@ -21924,7 +21928,7 @@ namespace ts {
21924
21928
21925
21929
// Only check rest parameter type if it's not a binding pattern. Since binding patterns are
21926
21930
// not allowed in a rest parameter, we already have an error from checkGrammarParameterList.
21927
- if (node.dotDotDotToken && !isBindingPattern(node.name) && !isRestParameterType (getTypeOfSymbol(node.symbol))) {
21931
+ if (node.dotDotDotToken && !isBindingPattern(node.name) && !isTypeAssignableTo (getTypeOfSymbol(node.symbol), anyArrayType )) {
21928
21932
error(node, Diagnostics.A_rest_parameter_must_be_of_an_array_type);
21929
21933
}
21930
21934
}
0 commit comments