Skip to content

Commit e239f86

Browse files
committed
Flatten spread expressions of tuple types
1 parent 9ae9371 commit e239f86

2 files changed

Lines changed: 28 additions & 2 deletions

File tree

src/compiler/checker.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18097,7 +18097,25 @@ namespace ts {
1809718097
return node.attributes.properties.length > 0 ? [node.attributes] : emptyArray;
1809818098
}
1809918099
else {
18100-
return node.arguments || emptyArray;
18100+
const args = node.arguments || emptyArray;
18101+
const length = args.length;
18102+
if (length && args[length - 1].kind === SyntaxKind.SpreadElement && getSpreadArgumentIndex(args) === length - 1) {
18103+
// We have a spread argument in the last position and no other spread arguments. If the type
18104+
// of the argument is a tuple type, spread the tuple elements into the argument list. We can
18105+
// call checkExpressionCached because spread expressions never have a contextual type.
18106+
const spreadArgument = <SpreadElement>args[length - 1];
18107+
const type = checkExpressionCached(spreadArgument.expression);
18108+
if (isTupleType(type)) {
18109+
const syntheticArgs = map((<TypeReference>type).typeArguments || emptyArray, t => {
18110+
const arg = <SyntheticExpression>createNode(SyntaxKind.SyntheticExpression, spreadArgument.pos, spreadArgument.end);
18111+
arg.parent = spreadArgument;
18112+
arg.type = t;
18113+
return arg;
18114+
});
18115+
return concatenate(args.slice(0, length - 1), syntheticArgs);
18116+
}
18117+
}
18118+
return args;
1810118119
}
1810218120
}
1810318121

@@ -21015,6 +21033,8 @@ namespace ts {
2101521033
return undefinedWideningType;
2101621034
case SyntaxKind.YieldExpression:
2101721035
return checkYieldExpression(<YieldExpression>node);
21036+
case SyntaxKind.SyntheticExpression:
21037+
return (<SyntheticExpression>node).type;
2101821038
case SyntaxKind.JsxExpression:
2101921039
return checkJsxExpression(<JsxExpression>node, checkMode);
2102021040
case SyntaxKind.JsxElement:
@@ -21059,7 +21079,7 @@ namespace ts {
2105921079
}
2106021080

2106121081
function isRestParameterType(type: Type) {
21062-
return isArrayType(type) || isTupleType(type) || type.flags & TypeFlags.TypeParameter && isArrayType(getBaseConstraintOfType(type) || unknownType);
21082+
return isArrayType(type) || isTupleType(type) || type.flags & TypeFlags.Instantiable && isTypeAssignableTo(type, anyArrayType);
2106321083
}
2106421084

2106521085
function checkParameter(node: ParameterDeclaration) {

src/compiler/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ namespace ts {
320320
AsExpression,
321321
NonNullExpression,
322322
MetaProperty,
323+
SyntheticExpression,
323324

324325
// Misc
325326
TemplateSpan,
@@ -1338,6 +1339,11 @@ namespace ts {
13381339
expression?: Expression;
13391340
}
13401341

1342+
export interface SyntheticExpression extends Expression {
1343+
kind: SyntaxKind.SyntheticExpression;
1344+
type: Type;
1345+
}
1346+
13411347
// see: https://tc39.github.io/ecma262/#prod-ExponentiationExpression
13421348
export type ExponentiationOperator
13431349
= SyntaxKind.AsteriskAsteriskToken

0 commit comments

Comments
 (0)