Merge pull request #26676 from Microsoft/complexRestParameterTypes

Improve checking of complex rest parameter types
This commit is contained in:
Anders Hejlsberg 2018-08-29 11:39:04 -07:00 committed by GitHub
commit d066e1e9e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 838 additions and 188 deletions

View file

@ -7823,8 +7823,12 @@ namespace ts {
}
function tryGetRestTypeOfSignature(signature: Signature): Type | undefined {
const type = getTypeOfRestParameter(signature);
return type && getIndexTypeOfType(type, IndexKind.Number);
if (signature.hasRestParameter) {
const sigRestType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
const restType = isTupleType(sigRestType) ? getRestTypeOfTupleType(sigRestType) : sigRestType;
return restType && getIndexTypeOfType(restType, IndexKind.Number);
}
return undefined;
}
function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean): Signature {
@ -10720,9 +10724,10 @@ namespace ts {
}
const sourceCount = getParameterCount(source);
const sourceGenericRestType = getGenericRestType(source);
const targetGenericRestType = sourceGenericRestType ? getGenericRestType(target) : undefined;
if (sourceGenericRestType && !(targetGenericRestType && sourceCount === targetCount)) {
const sourceRestType = getNonArrayRestType(source);
const targetRestType = getNonArrayRestType(target);
if (sourceRestType && targetRestType && sourceCount !== targetCount) {
// We're not able to relate misaligned complex rest parameters
return Ternary.False;
}
@ -10748,11 +10753,12 @@ namespace ts {
}
}
const paramCount = Math.max(sourceCount, targetCount);
const lastIndex = paramCount - 1;
const paramCount = sourceRestType || targetRestType ? Math.min(sourceCount, targetCount) : Math.max(sourceCount, targetCount);
const restIndex = sourceRestType || targetRestType ? paramCount - 1 : -1;
for (let i = 0; i < paramCount; i++) {
const sourceType = i === lastIndex && sourceGenericRestType || getTypeAtPosition(source, i);
const targetType = i === lastIndex && targetGenericRestType || getTypeAtPosition(target, i);
const sourceType = i === restIndex ? getRestTypeAtPosition(source, i) : getTypeAtPosition(source, i);
const targetType = i === restIndex ? getRestTypeAtPosition(target, i) : getTypeAtPosition(target, i);
// In order to ensure that any generic type Foo<T> is at least co-variant with respect to T no matter
// how Foo uses T, we need to relate parameters bi-variantly (given that parameters are input positions,
// they naturally relate only contra-variantly). However, if the source and target parameters both have
@ -12704,6 +12710,11 @@ namespace ts {
return type.target.hasRestElement ? type.typeArguments![type.target.typeParameters!.length - 1] : undefined;
}
function getRestArrayTypeOfTupleType(type: TupleTypeReference) {
const restType = getRestTypeOfTupleType(type);
return restType && createArrayType(restType);
}
function getLengthOfTupleType(type: TupleTypeReference) {
return getTypeReferenceArity(type) - (type.target.hasRestElement ? 1 : 0);
}
@ -13049,19 +13060,16 @@ namespace ts {
function forEachMatchingParameterType(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) {
const sourceCount = getParameterCount(source);
const targetCount = getParameterCount(target);
const sourceHasRest = hasEffectiveRestParameter(source);
const targetHasRest = hasEffectiveRestParameter(target);
const maxCount = sourceHasRest && targetHasRest ? Math.max(sourceCount, targetCount) :
sourceHasRest ? targetCount :
targetHasRest ? sourceCount :
const sourceRestType = getEffectiveRestType(source);
const targetRestType = getEffectiveRestType(target);
const paramCount = targetRestType ? Math.min(targetCount - 1, sourceCount) :
sourceRestType ? targetCount :
Math.min(sourceCount, targetCount);
const targetGenericRestType = getGenericRestType(target);
const paramCount = targetGenericRestType ? Math.min(targetCount - 1, maxCount) : maxCount;
for (let i = 0; i < paramCount; i++) {
callback(getTypeAtPosition(source, i), getTypeAtPosition(target, i));
}
if (targetGenericRestType) {
callback(getRestTypeAtPosition(source, paramCount), targetGenericRestType);
if (targetRestType) {
callback(getRestTypeAtPosition(source, paramCount), targetRestType);
}
}
@ -13521,32 +13529,37 @@ namespace ts {
}
function inferFromProperties(source: Type, target: Type) {
if (isTupleType(source) && isTupleType(target)) {
const sourceLength = getLengthOfTupleType(source);
const targetLength = getLengthOfTupleType(target);
const sourceRestType = getRestTypeOfTupleType(source);
const targetRestType = getRestTypeOfTupleType(target);
const fixedLength = targetLength < sourceLength || sourceRestType ? targetLength : sourceLength;
for (let i = 0; i < fixedLength; i++) {
inferFromTypes(i < sourceLength ? source.typeArguments![i] : sourceRestType!, target.typeArguments![i]);
if (isTupleType(source)) {
if (isTupleType(target)) {
const sourceLength = getLengthOfTupleType(source);
const targetLength = getLengthOfTupleType(target);
const sourceRestType = getRestTypeOfTupleType(source);
const targetRestType = getRestTypeOfTupleType(target);
const fixedLength = targetLength < sourceLength || sourceRestType ? targetLength : sourceLength;
for (let i = 0; i < fixedLength; i++) {
inferFromTypes(i < sourceLength ? source.typeArguments![i] : sourceRestType!, target.typeArguments![i]);
}
if (targetRestType) {
const types = fixedLength < sourceLength ? source.typeArguments!.slice(fixedLength, sourceLength) : [];
if (sourceRestType) {
types.push(sourceRestType);
}
if (types.length) {
inferFromTypes(getUnionType(types), targetRestType);
}
}
return;
}
if (targetRestType) {
const types = fixedLength < sourceLength ? source.typeArguments!.slice(fixedLength, sourceLength) : [];
if (sourceRestType) {
types.push(sourceRestType);
}
if (types.length) {
inferFromTypes(getUnionType(types), targetRestType);
}
if (isArrayType(target)) {
inferFromIndexTypes(source, target);
return;
}
}
else {
const properties = getPropertiesOfObjectType(target);
for (const targetProp of properties) {
const sourceProp = getPropertyOfType(source, targetProp.escapedName);
if (sourceProp) {
inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
}
const properties = getPropertiesOfObjectType(target);
for (const targetProp of properties) {
const sourceProp = getPropertyOfType(source, targetProp.escapedName);
if (sourceProp) {
inferFromTypes(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp));
}
}
}
@ -18693,8 +18706,8 @@ namespace ts {
inferTypes(context.inferences, thisArgumentType, thisType);
}
const genericRestType = getGenericRestType(signature);
const argCount = genericRestType ? Math.min(getParameterCount(signature) - 1, args.length) : args.length;
const restType = getNonArrayRestType(signature);
const argCount = restType ? Math.min(getParameterCount(signature) - 1, args.length) : args.length;
for (let i = 0; i < argCount; i++) {
const arg = args[i];
if (arg.kind !== SyntaxKind.OmittedExpression) {
@ -18707,14 +18720,21 @@ namespace ts {
}
}
if (genericRestType) {
const spreadType = getSpreadArgumentType(args, argCount, args.length, genericRestType, context);
inferTypes(context.inferences, spreadType, genericRestType);
if (restType) {
const spreadType = getSpreadArgumentType(args, argCount, args.length, restType, context);
inferTypes(context.inferences, spreadType, restType);
}
return getInferredTypes(context);
}
function getArrayifiedType(type: Type) {
if (forEachType(type, t => !(t.flags & (TypeFlags.Any | TypeFlags.Instantiable) || isArrayType(t) || isTupleType(t)))) {
return createArrayType(getIndexTypeOfType(type, IndexKind.Number) || errorType);
}
return type;
}
function getSpreadArgumentType(args: ReadonlyArray<Expression>, index: number, argCount: number, restType: TypeParameter, context: InferenceContext | undefined) {
if (index >= argCount - 1) {
const arg = args[argCount - 1];
@ -18723,7 +18743,7 @@ namespace ts {
// and the argument are ...x forms.
return arg.kind === SyntaxKind.SyntheticExpression ?
createArrayType((<SyntheticExpression>arg).type) :
checkExpressionWithContextualType((<SpreadElement>arg).expression, restType, context);
getArrayifiedType(checkExpressionWithContextualType((<SpreadElement>arg).expression, restType, context));
}
}
const contextualType = getIndexTypeOfType(restType, IndexKind.Number) || anyType;
@ -18828,28 +18848,27 @@ namespace ts {
}
}
const headMessage = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1;
const restIndex = signature.hasRestParameter ? signature.parameters.length - 1 : -1;
const restType = restIndex >= 0 ? getTypeOfSymbol(signature.parameters[restIndex]) : anyType;
for (let i = 0; i < args.length; i++) {
const restType = getNonArrayRestType(signature);
const argCount = restType ? Math.min(getParameterCount(signature) - 1, args.length) : args.length;
for (let i = 0; i < argCount; i++) {
const arg = args[i];
if (arg.kind !== SyntaxKind.OmittedExpression) {
if (i === restIndex && (restType.flags & TypeFlags.TypeParameter || isSpreadArgument(arg) && !isArrayType(restType))) {
const spreadType = getSpreadArgumentType(args, i, args.length, restType, /*context*/ undefined);
return checkTypeRelatedTo(spreadType, restType, relation, arg, headMessage);
}
else {
const paramType = getTypeAtPosition(signature, i);
const argType = checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
// If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter),
// we obtain the regular type of any object literal arguments because we may not have inferred complete
// parameter types yet and therefore excess property checks may yield false positives (see #17041).
const checkArgType = excludeArgument ? getRegularTypeOfObjectLiteral(argType) : argType;
if (!checkTypeRelatedTo(checkArgType, paramType, relation, reportErrors ? arg : undefined, headMessage)) {
return false;
}
const paramType = getTypeAtPosition(signature, i);
const argType = checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
// If one or more arguments are still excluded (as indicated by a non-null excludeArgument parameter),
// we obtain the regular type of any object literal arguments because we may not have inferred complete
// parameter types yet and therefore excess property checks may yield false positives (see #17041).
const checkArgType = excludeArgument ? getRegularTypeOfObjectLiteral(argType) : argType;
if (!checkTypeRelatedTo(checkArgType, paramType, relation, reportErrors ? arg : undefined, headMessage)) {
return false;
}
}
}
if (restType) {
const spreadType = getSpreadArgumentType(args, argCount, args.length, restType, /*context*/ undefined);
const errorNode = reportErrors ? argCount < args.length ? args[argCount] : node : undefined;
return checkTypeRelatedTo(spreadType, restType, relation, errorNode, headMessage);
}
return true;
}
@ -19189,7 +19208,7 @@ namespace ts {
checkCandidate = getSignatureInstantiation(candidate, typeArgumentTypes, isInJavaScriptFile(candidate.declaration));
// If the original signature has a generic rest type, instantiation may produce a
// signature with different arity and we need to perform another arity check.
if (getGenericRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) {
if (getNonArrayRestType(candidate) && !hasCorrectArity(node, args, checkCandidate, signatureHelpTrailingComma)) {
candidateForArgumentArityError = checkCandidate;
continue;
}
@ -20167,14 +20186,11 @@ namespace ts {
function getRestTypeAtPosition(source: Signature, pos: number): Type {
const paramCount = getParameterCount(source);
const hasRest = hasEffectiveRestParameter(source);
if (hasRest && pos === paramCount - 1) {
const genericRestType = getGenericRestType(source);
if (genericRestType) {
return genericRestType;
}
const restType = getEffectiveRestType(source);
if (restType && pos === paramCount - 1) {
return restType;
}
const start = hasRest ? Math.min(pos, paramCount - 1) : pos;
const start = restType ? Math.min(pos, paramCount - 1) : pos;
const types = [];
const names = [];
for (let i = start; i < paramCount; i++) {
@ -20183,18 +20199,7 @@ namespace ts {
}
const minArgumentCount = getMinArgumentCount(source);
const minLength = minArgumentCount < start ? 0 : minArgumentCount - start;
return createTupleType(types, minLength, hasRest, names);
}
function getTypeOfRestParameter(signature: Signature) {
if (signature.hasRestParameter) {
const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
if (isTupleType(restType)) {
return getRestTypeOfTupleType(restType);
}
return restType;
}
return undefined;
return createTupleType(types, minLength, !!restType, names);
}
function getParameterCount(signature: Signature) {
@ -20221,16 +20226,6 @@ namespace ts {
return signature.minArgumentCount;
}
function getGenericRestType(signature: Signature) {
if (signature.hasRestParameter) {
const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
if (restType.flags & TypeFlags.Instantiable) {
return restType;
}
}
return undefined;
}
function hasEffectiveRestParameter(signature: Signature) {
if (signature.hasRestParameter) {
const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
@ -20239,6 +20234,19 @@ namespace ts {
return false;
}
function getEffectiveRestType(signature: Signature) {
if (signature.hasRestParameter) {
const restType = getTypeOfSymbol(signature.parameters[signature.parameters.length - 1]);
return isTupleType(restType) ? getRestArrayTypeOfTupleType(restType) : restType;
}
return undefined;
}
function getNonArrayRestType(signature: Signature) {
const restType = getEffectiveRestType(signature);
return restType && !isArrayType(restType) && !isTypeAny(restType) ? restType : undefined;
}
function getTypeOfFirstParameterOfSignature(signature: Signature) {
return getTypeOfFirstParameterOfSignatureWithFallback(signature, neverType);
}
@ -21928,10 +21936,6 @@ namespace ts {
}
}
function isRestParameterType(type: Type) {
return isArrayType(type) || isTupleType(type) || type.flags & TypeFlags.Instantiable && isTypeAssignableTo(type, anyArrayType);
}
function checkParameter(node: ParameterDeclaration) {
// Grammar checking
// It is a SyntaxError if the Identifier "eval" or the Identifier "arguments" occurs as the
@ -21963,7 +21967,7 @@ namespace ts {
// Only check rest parameter type if it's not a binding pattern. Since binding patterns are
// not allowed in a rest parameter, we already have an error from checkGrammarParameterList.
if (node.dotDotDotToken && !isBindingPattern(node.name) && !isRestParameterType(getTypeOfSymbol(node.symbol))) {
if (node.dotDotDotToken && !isBindingPattern(node.name) && !isTypeAssignableTo(getTypeOfSymbol(node.symbol), anyArrayType)) {
error(node, Diagnostics.A_rest_parameter_must_be_of_an_array_type);
}
}

View file

@ -1,4 +1,3 @@
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(13,13): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(14,17): error TS1047: A rest parameter cannot be optional.
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(15,16): error TS1048: A rest parameter cannot have an initializer.
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(20,19): error TS2345: Argument of type 'true' is not assignable to parameter of type 'string | number'.
@ -16,7 +15,7 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(
tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(34,28): error TS2304: Cannot find name 'E'.
==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts (11 errors) ====
==== tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts (10 errors) ====
// If the parameter is a rest parameter, the parameter type is any[]
// A type annotation for a rest parameter must denote an array type.
@ -30,8 +29,6 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(
function a0(...x: [number, number, string]) { } // Error, rest parameter must be array type
function a1(...x: (number|string)[]) { }
function a2(...a: someArray) { } // Error, rest parameter must be array type
~~~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
function a3(...b?) { } // Error, can't be optional
~
!!! error TS1047: A rest parameter cannot be optional.

View file

@ -0,0 +1,148 @@
tests/cases/conformance/types/rest/genericRestParameters3.ts(11,11): error TS2345: Argument of type '[10]' is not assignable to parameter of type '[string] | [number, boolean]'.
Type '[10]' is not assignable to type '[string]'.
Type '10' is not assignable to type 'string'.
tests/cases/conformance/types/rest/genericRestParameters3.ts(12,1): error TS2345: Argument of type '[]' is not assignable to parameter of type '[string] | [number, boolean]'.
Type '[]' is not assignable to type '[number, boolean]'.
Property '0' is missing in type '[]'.
tests/cases/conformance/types/rest/genericRestParameters3.ts(16,1): error TS2322: Type '(x: string, ...args: [string] | [number, boolean]) => void' is not assignable to type '(...args: [string, string] | [string, number, boolean]) => void'.
tests/cases/conformance/types/rest/genericRestParameters3.ts(17,1): error TS2322: Type '(x: string, y: string) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
Types of parameters 'y' and 'args' are incompatible.
Type '[string] | [number, boolean]' is not assignable to type '[string]'.
Type '[number, boolean]' is not assignable to type '[string]'.
Types of property '0' are incompatible.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/types/rest/genericRestParameters3.ts(18,1): error TS2322: Type '(x: string, y: number, z: boolean) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
Types of parameters 'y' and 'args' are incompatible.
Type '[string] | [number, boolean]' is not assignable to type '[number, boolean]'.
Type '[string]' is not assignable to type '[number, boolean]'.
Property '1' is missing in type '[string]'.
tests/cases/conformance/types/rest/genericRestParameters3.ts(19,1): error TS2322: Type '(...args: [string, string] | [string, number, boolean]) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
tests/cases/conformance/types/rest/genericRestParameters3.ts(29,1): error TS2554: Expected 1 arguments, but got 0.
tests/cases/conformance/types/rest/genericRestParameters3.ts(30,21): error TS2345: Argument of type '100' is not assignable to parameter of type '(...args: CoolArray<any>) => void'.
tests/cases/conformance/types/rest/genericRestParameters3.ts(31,21): error TS2345: Argument of type '<T extends any[]>(cb: (...args: T) => void) => void' is not assignable to parameter of type '(...args: CoolArray<any>) => void'.
Types of parameters 'cb' and 'args' are incompatible.
Type 'CoolArray<any>' is not assignable to type '[(...args: any[]) => void]'.
Property '0' is missing in type 'CoolArray<any>'.
tests/cases/conformance/types/rest/genericRestParameters3.ts(38,32): error TS2345: Argument of type '[10, 20]' is not assignable to parameter of type 'CoolArray<number>'.
Property 'hello' is missing in type '[10, 20]'.
tests/cases/conformance/types/rest/genericRestParameters3.ts(43,1): error TS2345: Argument of type '[]' is not assignable to parameter of type 'CoolArray<never>'.
Property 'hello' is missing in type '[]'.
tests/cases/conformance/types/rest/genericRestParameters3.ts(44,5): error TS2345: Argument of type '[number]' is not assignable to parameter of type 'CoolArray<{}>'.
Property 'hello' is missing in type '[number]'.
tests/cases/conformance/types/rest/genericRestParameters3.ts(45,5): error TS2345: Argument of type '[number, number]' is not assignable to parameter of type 'CoolArray<{}>'.
Property 'hello' is missing in type '[number, number]'.
tests/cases/conformance/types/rest/genericRestParameters3.ts(46,5): error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'CoolArray<number>'.
Property 'hello' is missing in type 'number[]'.
tests/cases/conformance/types/rest/genericRestParameters3.ts(53,5): error TS2345: Argument of type '["what"]' is not assignable to parameter of type '[] | [number, string]'.
Type '["what"]' is not assignable to type '[number, string]'.
Property '1' is missing in type '["what"]'.
==== tests/cases/conformance/types/rest/genericRestParameters3.ts (15 errors) ====
declare let f1: (x: string, ...args: [string] | [number, boolean]) => void;
declare let f2: (x: string, y: string) => void;
declare let f3: (x: string, y: number, z: boolean) => void;
declare let f4: (...args: [string, string] | [string, number, boolean]) => void;
declare const tt: [string] | [number, boolean];
f1("foo", "abc");
f1("foo", 10, true);
f1("foo", ...tt);
f1("foo", 10); // Error
~~
!!! error TS2345: Argument of type '[10]' is not assignable to parameter of type '[string] | [number, boolean]'.
!!! error TS2345: Type '[10]' is not assignable to type '[string]'.
!!! error TS2345: Type '10' is not assignable to type 'string'.
f1("foo"); // Error
~~~~~~~~~
!!! error TS2345: Argument of type '[]' is not assignable to parameter of type '[string] | [number, boolean]'.
!!! error TS2345: Type '[]' is not assignable to type '[number, boolean]'.
!!! error TS2345: Property '0' is missing in type '[]'.
f2 = f1;
f3 = f1;
f4 = f1; // Error, misaligned complex rest types
~~
!!! error TS2322: Type '(x: string, ...args: [string] | [number, boolean]) => void' is not assignable to type '(...args: [string, string] | [string, number, boolean]) => void'.
f1 = f2; // Error
~~
!!! error TS2322: Type '(x: string, y: string) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
!!! error TS2322: Types of parameters 'y' and 'args' are incompatible.
!!! error TS2322: Type '[string] | [number, boolean]' is not assignable to type '[string]'.
!!! error TS2322: Type '[number, boolean]' is not assignable to type '[string]'.
!!! error TS2322: Types of property '0' are incompatible.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
f1 = f3; // Error
~~
!!! error TS2322: Type '(x: string, y: number, z: boolean) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
!!! error TS2322: Types of parameters 'y' and 'args' are incompatible.
!!! error TS2322: Type '[string] | [number, boolean]' is not assignable to type '[number, boolean]'.
!!! error TS2322: Type '[string]' is not assignable to type '[number, boolean]'.
!!! error TS2322: Property '1' is missing in type '[string]'.
f1 = f4; // Error, misaligned complex rest types
~~
!!! error TS2322: Type '(...args: [string, string] | [string, number, boolean]) => void' is not assignable to type '(x: string, ...args: [string] | [number, boolean]) => void'.
// Repro from #26110
interface CoolArray<E> extends Array<E> {
hello: number;
}
declare function foo<T extends any[]>(cb: (...args: T) => void): void;
foo<CoolArray<any>>(); // Error
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2554: Expected 1 arguments, but got 0.
foo<CoolArray<any>>(100); // Error
~~~
!!! error TS2345: Argument of type '100' is not assignable to parameter of type '(...args: CoolArray<any>) => void'.
foo<CoolArray<any>>(foo); // Error
~~~
!!! error TS2345: Argument of type '<T extends any[]>(cb: (...args: T) => void) => void' is not assignable to parameter of type '(...args: CoolArray<any>) => void'.
!!! error TS2345: Types of parameters 'cb' and 'args' are incompatible.
!!! error TS2345: Type 'CoolArray<any>' is not assignable to type '[(...args: any[]) => void]'.
!!! error TS2345: Property '0' is missing in type 'CoolArray<any>'.
function bar<T extends any[]>(...args: T): T {
return args;
}
let a = bar(10, 20);
let b = bar<CoolArray<number>>(10, 20); // Error
~~
!!! error TS2345: Argument of type '[10, 20]' is not assignable to parameter of type 'CoolArray<number>'.
!!! error TS2345: Property 'hello' is missing in type '[10, 20]'.
declare function baz<T>(...args: CoolArray<T>): void;
declare const ca: CoolArray<number>;
baz(); // Error
~~~~~
!!! error TS2345: Argument of type '[]' is not assignable to parameter of type 'CoolArray<never>'.
!!! error TS2345: Property 'hello' is missing in type '[]'.
baz(1); // Error
~
!!! error TS2345: Argument of type '[number]' is not assignable to parameter of type 'CoolArray<{}>'.
!!! error TS2345: Property 'hello' is missing in type '[number]'.
baz(1, 2); // Error
~
!!! error TS2345: Argument of type '[number, number]' is not assignable to parameter of type 'CoolArray<{}>'.
!!! error TS2345: Property 'hello' is missing in type '[number, number]'.
baz(...ca); // Error
~~~~~
!!! error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'CoolArray<number>'.
!!! error TS2345: Property 'hello' is missing in type 'number[]'.
// Repro from #26491
declare function hmm<A extends [] | [number, string]>(...args: A): void;
hmm(); // okay, A = []
hmm(1, "s"); // okay, A = [1, "s"]
hmm("what"); // no error? A = [] | [number, string] ?
~~~~~~
!!! error TS2345: Argument of type '["what"]' is not assignable to parameter of type '[] | [number, string]'.
!!! error TS2345: Type '["what"]' is not assignable to type '[number, string]'.
!!! error TS2345: Property '1' is missing in type '["what"]'.

View file

@ -0,0 +1,106 @@
//// [genericRestParameters3.ts]
declare let f1: (x: string, ...args: [string] | [number, boolean]) => void;
declare let f2: (x: string, y: string) => void;
declare let f3: (x: string, y: number, z: boolean) => void;
declare let f4: (...args: [string, string] | [string, number, boolean]) => void;
declare const tt: [string] | [number, boolean];
f1("foo", "abc");
f1("foo", 10, true);
f1("foo", ...tt);
f1("foo", 10); // Error
f1("foo"); // Error
f2 = f1;
f3 = f1;
f4 = f1; // Error, misaligned complex rest types
f1 = f2; // Error
f1 = f3; // Error
f1 = f4; // Error, misaligned complex rest types
// Repro from #26110
interface CoolArray<E> extends Array<E> {
hello: number;
}
declare function foo<T extends any[]>(cb: (...args: T) => void): void;
foo<CoolArray<any>>(); // Error
foo<CoolArray<any>>(100); // Error
foo<CoolArray<any>>(foo); // Error
function bar<T extends any[]>(...args: T): T {
return args;
}
let a = bar(10, 20);
let b = bar<CoolArray<number>>(10, 20); // Error
declare function baz<T>(...args: CoolArray<T>): void;
declare const ca: CoolArray<number>;
baz(); // Error
baz(1); // Error
baz(1, 2); // Error
baz(...ca); // Error
// Repro from #26491
declare function hmm<A extends [] | [number, string]>(...args: A): void;
hmm(); // okay, A = []
hmm(1, "s"); // okay, A = [1, "s"]
hmm("what"); // no error? A = [] | [number, string] ?
//// [genericRestParameters3.js]
"use strict";
f1("foo", "abc");
f1("foo", 10, true);
f1.apply(void 0, ["foo"].concat(tt));
f1("foo", 10); // Error
f1("foo"); // Error
f2 = f1;
f3 = f1;
f4 = f1; // Error, misaligned complex rest types
f1 = f2; // Error
f1 = f3; // Error
f1 = f4; // Error, misaligned complex rest types
foo(); // Error
foo(100); // Error
foo(foo); // Error
function bar() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return args;
}
var a = bar(10, 20);
var b = bar(10, 20); // Error
baz(); // Error
baz(1); // Error
baz(1, 2); // Error
baz.apply(void 0, ca); // Error
hmm(); // okay, A = []
hmm(1, "s"); // okay, A = [1, "s"]
hmm("what"); // no error? A = [] | [number, string] ?
//// [genericRestParameters3.d.ts]
declare let f1: (x: string, ...args: [string] | [number, boolean]) => void;
declare let f2: (x: string, y: string) => void;
declare let f3: (x: string, y: number, z: boolean) => void;
declare let f4: (...args: [string, string] | [string, number, boolean]) => void;
declare const tt: [string] | [number, boolean];
interface CoolArray<E> extends Array<E> {
hello: number;
}
declare function foo<T extends any[]>(cb: (...args: T) => void): void;
declare function bar<T extends any[]>(...args: T): T;
declare let a: [number, number];
declare let b: any;
declare function baz<T>(...args: CoolArray<T>): void;
declare const ca: CoolArray<number>;
declare function hmm<A extends [] | [number, string]>(...args: A): void;

View file

@ -0,0 +1,157 @@
=== tests/cases/conformance/types/rest/genericRestParameters3.ts ===
declare let f1: (x: string, ...args: [string] | [number, boolean]) => void;
>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11))
>x : Symbol(x, Decl(genericRestParameters3.ts, 0, 17))
>args : Symbol(args, Decl(genericRestParameters3.ts, 0, 27))
declare let f2: (x: string, y: string) => void;
>f2 : Symbol(f2, Decl(genericRestParameters3.ts, 1, 11))
>x : Symbol(x, Decl(genericRestParameters3.ts, 1, 17))
>y : Symbol(y, Decl(genericRestParameters3.ts, 1, 27))
declare let f3: (x: string, y: number, z: boolean) => void;
>f3 : Symbol(f3, Decl(genericRestParameters3.ts, 2, 11))
>x : Symbol(x, Decl(genericRestParameters3.ts, 2, 17))
>y : Symbol(y, Decl(genericRestParameters3.ts, 2, 27))
>z : Symbol(z, Decl(genericRestParameters3.ts, 2, 38))
declare let f4: (...args: [string, string] | [string, number, boolean]) => void;
>f4 : Symbol(f4, Decl(genericRestParameters3.ts, 3, 11))
>args : Symbol(args, Decl(genericRestParameters3.ts, 3, 17))
declare const tt: [string] | [number, boolean];
>tt : Symbol(tt, Decl(genericRestParameters3.ts, 5, 13))
f1("foo", "abc");
>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11))
f1("foo", 10, true);
>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11))
f1("foo", ...tt);
>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11))
>tt : Symbol(tt, Decl(genericRestParameters3.ts, 5, 13))
f1("foo", 10); // Error
>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11))
f1("foo"); // Error
>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11))
f2 = f1;
>f2 : Symbol(f2, Decl(genericRestParameters3.ts, 1, 11))
>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11))
f3 = f1;
>f3 : Symbol(f3, Decl(genericRestParameters3.ts, 2, 11))
>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11))
f4 = f1; // Error, misaligned complex rest types
>f4 : Symbol(f4, Decl(genericRestParameters3.ts, 3, 11))
>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11))
f1 = f2; // Error
>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11))
>f2 : Symbol(f2, Decl(genericRestParameters3.ts, 1, 11))
f1 = f3; // Error
>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11))
>f3 : Symbol(f3, Decl(genericRestParameters3.ts, 2, 11))
f1 = f4; // Error, misaligned complex rest types
>f1 : Symbol(f1, Decl(genericRestParameters3.ts, 0, 11))
>f4 : Symbol(f4, Decl(genericRestParameters3.ts, 3, 11))
// Repro from #26110
interface CoolArray<E> extends Array<E> {
>CoolArray : Symbol(CoolArray, Decl(genericRestParameters3.ts, 18, 8))
>E : Symbol(E, Decl(genericRestParameters3.ts, 22, 20))
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>E : Symbol(E, Decl(genericRestParameters3.ts, 22, 20))
hello: number;
>hello : Symbol(CoolArray.hello, Decl(genericRestParameters3.ts, 22, 41))
}
declare function foo<T extends any[]>(cb: (...args: T) => void): void;
>foo : Symbol(foo, Decl(genericRestParameters3.ts, 24, 1))
>T : Symbol(T, Decl(genericRestParameters3.ts, 26, 21))
>cb : Symbol(cb, Decl(genericRestParameters3.ts, 26, 38))
>args : Symbol(args, Decl(genericRestParameters3.ts, 26, 43))
>T : Symbol(T, Decl(genericRestParameters3.ts, 26, 21))
foo<CoolArray<any>>(); // Error
>foo : Symbol(foo, Decl(genericRestParameters3.ts, 24, 1))
>CoolArray : Symbol(CoolArray, Decl(genericRestParameters3.ts, 18, 8))
foo<CoolArray<any>>(100); // Error
>foo : Symbol(foo, Decl(genericRestParameters3.ts, 24, 1))
>CoolArray : Symbol(CoolArray, Decl(genericRestParameters3.ts, 18, 8))
foo<CoolArray<any>>(foo); // Error
>foo : Symbol(foo, Decl(genericRestParameters3.ts, 24, 1))
>CoolArray : Symbol(CoolArray, Decl(genericRestParameters3.ts, 18, 8))
>foo : Symbol(foo, Decl(genericRestParameters3.ts, 24, 1))
function bar<T extends any[]>(...args: T): T {
>bar : Symbol(bar, Decl(genericRestParameters3.ts, 30, 25))
>T : Symbol(T, Decl(genericRestParameters3.ts, 32, 13))
>args : Symbol(args, Decl(genericRestParameters3.ts, 32, 30))
>T : Symbol(T, Decl(genericRestParameters3.ts, 32, 13))
>T : Symbol(T, Decl(genericRestParameters3.ts, 32, 13))
return args;
>args : Symbol(args, Decl(genericRestParameters3.ts, 32, 30))
}
let a = bar(10, 20);
>a : Symbol(a, Decl(genericRestParameters3.ts, 36, 3))
>bar : Symbol(bar, Decl(genericRestParameters3.ts, 30, 25))
let b = bar<CoolArray<number>>(10, 20); // Error
>b : Symbol(b, Decl(genericRestParameters3.ts, 37, 3))
>bar : Symbol(bar, Decl(genericRestParameters3.ts, 30, 25))
>CoolArray : Symbol(CoolArray, Decl(genericRestParameters3.ts, 18, 8))
declare function baz<T>(...args: CoolArray<T>): void;
>baz : Symbol(baz, Decl(genericRestParameters3.ts, 37, 39))
>T : Symbol(T, Decl(genericRestParameters3.ts, 39, 21))
>args : Symbol(args, Decl(genericRestParameters3.ts, 39, 24))
>CoolArray : Symbol(CoolArray, Decl(genericRestParameters3.ts, 18, 8))
>T : Symbol(T, Decl(genericRestParameters3.ts, 39, 21))
declare const ca: CoolArray<number>;
>ca : Symbol(ca, Decl(genericRestParameters3.ts, 40, 13))
>CoolArray : Symbol(CoolArray, Decl(genericRestParameters3.ts, 18, 8))
baz(); // Error
>baz : Symbol(baz, Decl(genericRestParameters3.ts, 37, 39))
baz(1); // Error
>baz : Symbol(baz, Decl(genericRestParameters3.ts, 37, 39))
baz(1, 2); // Error
>baz : Symbol(baz, Decl(genericRestParameters3.ts, 37, 39))
baz(...ca); // Error
>baz : Symbol(baz, Decl(genericRestParameters3.ts, 37, 39))
>ca : Symbol(ca, Decl(genericRestParameters3.ts, 40, 13))
// Repro from #26491
declare function hmm<A extends [] | [number, string]>(...args: A): void;
>hmm : Symbol(hmm, Decl(genericRestParameters3.ts, 45, 11))
>A : Symbol(A, Decl(genericRestParameters3.ts, 49, 21))
>args : Symbol(args, Decl(genericRestParameters3.ts, 49, 54))
>A : Symbol(A, Decl(genericRestParameters3.ts, 49, 21))
hmm(); // okay, A = []
>hmm : Symbol(hmm, Decl(genericRestParameters3.ts, 45, 11))
hmm(1, "s"); // okay, A = [1, "s"]
>hmm : Symbol(hmm, Decl(genericRestParameters3.ts, 45, 11))
hmm("what"); // no error? A = [] | [number, string] ?
>hmm : Symbol(hmm, Decl(genericRestParameters3.ts, 45, 11))

View file

@ -0,0 +1,182 @@
=== tests/cases/conformance/types/rest/genericRestParameters3.ts ===
declare let f1: (x: string, ...args: [string] | [number, boolean]) => void;
>f1 : (x: string, ...args: [string] | [number, boolean]) => void
>x : string
>args : [string] | [number, boolean]
declare let f2: (x: string, y: string) => void;
>f2 : (x: string, y: string) => void
>x : string
>y : string
declare let f3: (x: string, y: number, z: boolean) => void;
>f3 : (x: string, y: number, z: boolean) => void
>x : string
>y : number
>z : boolean
declare let f4: (...args: [string, string] | [string, number, boolean]) => void;
>f4 : (...args: [string, string] | [string, number, boolean]) => void
>args : [string, string] | [string, number, boolean]
declare const tt: [string] | [number, boolean];
>tt : [string] | [number, boolean]
f1("foo", "abc");
>f1("foo", "abc") : void
>f1 : (x: string, ...args: [string] | [number, boolean]) => void
>"foo" : "foo"
>"abc" : "abc"
f1("foo", 10, true);
>f1("foo", 10, true) : void
>f1 : (x: string, ...args: [string] | [number, boolean]) => void
>"foo" : "foo"
>10 : 10
>true : true
f1("foo", ...tt);
>f1("foo", ...tt) : void
>f1 : (x: string, ...args: [string] | [number, boolean]) => void
>"foo" : "foo"
>...tt : string | number | boolean
>tt : [string] | [number, boolean]
f1("foo", 10); // Error
>f1("foo", 10) : void
>f1 : (x: string, ...args: [string] | [number, boolean]) => void
>"foo" : "foo"
>10 : 10
f1("foo"); // Error
>f1("foo") : void
>f1 : (x: string, ...args: [string] | [number, boolean]) => void
>"foo" : "foo"
f2 = f1;
>f2 = f1 : (x: string, ...args: [string] | [number, boolean]) => void
>f2 : (x: string, y: string) => void
>f1 : (x: string, ...args: [string] | [number, boolean]) => void
f3 = f1;
>f3 = f1 : (x: string, ...args: [string] | [number, boolean]) => void
>f3 : (x: string, y: number, z: boolean) => void
>f1 : (x: string, ...args: [string] | [number, boolean]) => void
f4 = f1; // Error, misaligned complex rest types
>f4 = f1 : (x: string, ...args: [string] | [number, boolean]) => void
>f4 : (...args: [string, string] | [string, number, boolean]) => void
>f1 : (x: string, ...args: [string] | [number, boolean]) => void
f1 = f2; // Error
>f1 = f2 : (x: string, y: string) => void
>f1 : (x: string, ...args: [string] | [number, boolean]) => void
>f2 : (x: string, y: string) => void
f1 = f3; // Error
>f1 = f3 : (x: string, y: number, z: boolean) => void
>f1 : (x: string, ...args: [string] | [number, boolean]) => void
>f3 : (x: string, y: number, z: boolean) => void
f1 = f4; // Error, misaligned complex rest types
>f1 = f4 : (...args: [string, string] | [string, number, boolean]) => void
>f1 : (x: string, ...args: [string] | [number, boolean]) => void
>f4 : (...args: [string, string] | [string, number, boolean]) => void
// Repro from #26110
interface CoolArray<E> extends Array<E> {
hello: number;
>hello : number
}
declare function foo<T extends any[]>(cb: (...args: T) => void): void;
>foo : <T extends any[]>(cb: (...args: T) => void) => void
>cb : (...args: T) => void
>args : T
foo<CoolArray<any>>(); // Error
>foo<CoolArray<any>>() : any
>foo : <T extends any[]>(cb: (...args: T) => void) => void
foo<CoolArray<any>>(100); // Error
>foo<CoolArray<any>>(100) : any
>foo : <T extends any[]>(cb: (...args: T) => void) => void
>100 : 100
foo<CoolArray<any>>(foo); // Error
>foo<CoolArray<any>>(foo) : any
>foo : <T extends any[]>(cb: (...args: T) => void) => void
>foo : <T extends any[]>(cb: (...args: T) => void) => void
function bar<T extends any[]>(...args: T): T {
>bar : <T extends any[]>(...args: T) => T
>args : T
return args;
>args : T
}
let a = bar(10, 20);
>a : [number, number]
>bar(10, 20) : [number, number]
>bar : <T extends any[]>(...args: T) => T
>10 : 10
>20 : 20
let b = bar<CoolArray<number>>(10, 20); // Error
>b : any
>bar<CoolArray<number>>(10, 20) : any
>bar : <T extends any[]>(...args: T) => T
>10 : 10
>20 : 20
declare function baz<T>(...args: CoolArray<T>): void;
>baz : <T>(...args: CoolArray<T>) => void
>args : CoolArray<T>
declare const ca: CoolArray<number>;
>ca : CoolArray<number>
baz(); // Error
>baz() : any
>baz : <T>(...args: CoolArray<T>) => void
baz(1); // Error
>baz(1) : any
>baz : <T>(...args: CoolArray<T>) => void
>1 : 1
baz(1, 2); // Error
>baz(1, 2) : any
>baz : <T>(...args: CoolArray<T>) => void
>1 : 1
>2 : 2
baz(...ca); // Error
>baz(...ca) : any
>baz : <T>(...args: CoolArray<T>) => void
>...ca : number
>ca : CoolArray<number>
// Repro from #26491
declare function hmm<A extends [] | [number, string]>(...args: A): void;
>hmm : <A extends [] | [number, string]>(...args: A) => void
>args : A
hmm(); // okay, A = []
>hmm() : void
>hmm : <A extends [] | [number, string]>(...args: A) => void
hmm(1, "s"); // okay, A = [1, "s"]
>hmm(1, "s") : void
>hmm : <A extends [] | [number, string]>(...args: A) => void
>1 : 1
>"s" : "s"
hmm("what"); // no error? A = [] | [number, string] ?
>hmm("what") : any
>hmm : <A extends [] | [number, string]>(...args: A) => void
>"what" : "what"

View file

@ -1,40 +1,12 @@
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(7,14): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(8,22): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(9,11): error TS1014: A rest parameter must be last in a parameter list.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(9,11): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(9,26): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(12,9): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(16,6): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(17,9): error TS1014: A rest parameter must be last in a parameter list.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(17,9): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(17,24): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(21,6): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(22,9): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(26,9): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(27,21): error TS1014: A rest parameter must be last in a parameter list.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(27,21): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(27,36): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(28,9): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(34,15): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(35,23): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(36,11): error TS1014: A rest parameter must be last in a parameter list.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(36,11): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(36,35): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(39,9): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(43,6): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(44,9): error TS1014: A rest parameter must be last in a parameter list.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(44,9): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(44,33): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(48,6): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(49,9): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(53,9): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(54,21): error TS1014: A rest parameter must be last in a parameter list.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(54,21): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(54,45): error TS2370: A rest parameter must be of an array type.
tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts(55,9): error TS2370: A rest parameter must be of an array type.
==== tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts (34 errors) ====
==== tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfNonArrayTypes2.ts (6 errors) ====
// Rest parameters must be an array type if they have a type annotation,
// user defined subtypes of array do not count, all of these are errors
@ -42,120 +14,64 @@ tests/cases/conformance/types/objectTypeLiteral/callSignatures/restParametersOfN
interface MyThing2<T> extends Array<T> { }
function foo(...x: MyThing) { }
~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
var f = function foo(...x: MyThing) { }
~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
var f2 = (...x: MyThing, ...y: MyThing) => { }
~~~
!!! error TS1014: A rest parameter must be last in a parameter list.
~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
class C {
foo(...x: MyThing) { }
~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
}
interface I {
(...x: MyThing);
~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
foo(...x: MyThing, ...y: MyThing);
~~~
!!! error TS1014: A rest parameter must be last in a parameter list.
~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
}
var a: {
(...x: MyThing);
~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
foo(...x: MyThing);
~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
}
var b = {
foo(...x: MyThing) { },
~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
a: function foo(...x: MyThing, ...y: MyThing) { },
~~~
!!! error TS1014: A rest parameter must be last in a parameter list.
~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
b: (...x: MyThing) => { }
~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
}
function foo2(...x: MyThing2<string>) { }
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
var f3 = function foo(...x: MyThing2<string>) { }
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
var f4 = (...x: MyThing2<string>, ...y: MyThing2<string>) => { }
~~~
!!! error TS1014: A rest parameter must be last in a parameter list.
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
class C2 {
foo(...x: MyThing2<string>) { }
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
}
interface I2 {
(...x: MyThing2<string>);
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
foo(...x: MyThing2<string>, ...y: MyThing2<string>);
~~~
!!! error TS1014: A rest parameter must be last in a parameter list.
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
}
var a2: {
(...x: MyThing2<string>);
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
foo(...x: MyThing2<string>);
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
}
var b2 = {
foo(...x: MyThing2<string>) { },
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
a: function foo(...x: MyThing2<string>, ...y: MyThing2<string>) { },
~~~
!!! error TS1014: A rest parameter must be last in a parameter list.
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
b: (...x: MyThing2<string>) => { }
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2370: A rest parameter must be of an array type.
}

View file

@ -0,0 +1,84 @@
tests/cases/conformance/types/rest/restTuplesFromContextualTypes.ts(56,7): error TS2345: Argument of type '(a: number, b: any, ...x: any[]) => void' is not assignable to parameter of type '(x: number, ...args: T) => void'.
Types of parameters 'b' and 'args' are incompatible.
Type 'T' is not assignable to type '[any, ...any[]]'.
Type 'any[]' is not assignable to type '[any, ...any[]]'.
Property '0' is missing in type 'any[]'.
==== tests/cases/conformance/types/rest/restTuplesFromContextualTypes.ts (1 errors) ====
declare const t1: [number, boolean, string];
(function (a, b, c){})(...t1);
(function (...x){})(...t1);
(function (a, ...x){})(...t1);
(function (a, b, ...x){})(...t1);
(function (a, b, c, ...x){})(...t1);
declare function f1(cb: (...args: typeof t1) => void): void;
f1((a, b, c) => {})
f1((...x) => {})
f1((a, ...x) => {})
f1((a, b, ...x) => {})
f1((a, b, c, ...x) => {})
declare const t2: [number, boolean, ...string[]];
(function (a, b, c){})(...t2);
(function (...x){})(...t2);
(function (a, ...x){})(...t2);
(function (a, b, ...x){})(...t2);
(function (a, b, c, ...x){})(...t2);
declare function f2(cb: (...args: typeof t2) => void): void;
f2((a, b, c) => {})
f2((...x) => {})
f2((a, ...x) => {})
f2((a, b, ...x) => {})
f2((a, b, c, ...x) => {})
declare const t3: [boolean, ...string[]];
(function (a, b, c){})(1, ...t3);
(function (...x){})(1, ...t3);
(function (a, ...x){})(1, ...t3);
(function (a, b, ...x){})(1, ...t3);
(function (a, b, c, ...x){})(1, ...t3);
declare function f3(cb: (x: number, ...args: typeof t3) => void): void;
f3((a, b, c) => {})
f3((...x) => {})
f3((a, ...x) => {})
f3((a, b, ...x) => {})
f3((a, b, c, ...x) => {})
function f4<T extends any[]>(t: T) {
(function(...x){})(...t);
(function(a, ...x){})(1, ...t);
(function(a, ...x){})(1, 2, ...t);
function f(cb: (x: number, ...args: T) => void) {}
f((...x) => {});
f((a, ...x) => {});
f((a, b, ...x) => {});
~~~~~~~~~~~~~~~~~~
!!! error TS2345: Argument of type '(a: number, b: any, ...x: any[]) => void' is not assignable to parameter of type '(x: number, ...args: T) => void'.
!!! error TS2345: Types of parameters 'b' and 'args' are incompatible.
!!! error TS2345: Type 'T' is not assignable to type '[any, ...any[]]'.
!!! error TS2345: Type 'any[]' is not assignable to type '[any, ...any[]]'.
!!! error TS2345: Property '0' is missing in type 'any[]'.
}
// Repro from #25288
declare var tuple: [number, string];
(function foo(a, b){}(...tuple));
// Repro from #25289
declare function take(cb: (a: number, b: string) => void): void;
(function foo(...rest){}(1, ''));
take(function(...rest){});

View file

@ -0,0 +1,56 @@
// @strict: true
// @declaration: true
declare let f1: (x: string, ...args: [string] | [number, boolean]) => void;
declare let f2: (x: string, y: string) => void;
declare let f3: (x: string, y: number, z: boolean) => void;
declare let f4: (...args: [string, string] | [string, number, boolean]) => void;
declare const tt: [string] | [number, boolean];
f1("foo", "abc");
f1("foo", 10, true);
f1("foo", ...tt);
f1("foo", 10); // Error
f1("foo"); // Error
f2 = f1;
f3 = f1;
f4 = f1; // Error, misaligned complex rest types
f1 = f2; // Error
f1 = f3; // Error
f1 = f4; // Error, misaligned complex rest types
// Repro from #26110
interface CoolArray<E> extends Array<E> {
hello: number;
}
declare function foo<T extends any[]>(cb: (...args: T) => void): void;
foo<CoolArray<any>>(); // Error
foo<CoolArray<any>>(100); // Error
foo<CoolArray<any>>(foo); // Error
function bar<T extends any[]>(...args: T): T {
return args;
}
let a = bar(10, 20);
let b = bar<CoolArray<number>>(10, 20); // Error
declare function baz<T>(...args: CoolArray<T>): void;
declare const ca: CoolArray<number>;
baz(); // Error
baz(1); // Error
baz(1, 2); // Error
baz(...ca); // Error
// Repro from #26491
declare function hmm<A extends [] | [number, string]>(...args: A): void;
hmm(); // okay, A = []
hmm(1, "s"); // okay, A = [1, "s"]
hmm("what"); // no error? A = [] | [number, string] ?