mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #24897 from Microsoft/restTuples
Tuples in rest parameters and spread expressions
This commit is contained in:
@@ -3606,6 +3606,8 @@ namespace ts {
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.ArrayType:
|
||||
case SyntaxKind.TupleType:
|
||||
case SyntaxKind.OptionalType:
|
||||
case SyntaxKind.RestType:
|
||||
case SyntaxKind.UnionType:
|
||||
case SyntaxKind.IntersectionType:
|
||||
case SyntaxKind.ConditionalType:
|
||||
|
||||
+566
-250
File diff suppressed because it is too large
Load Diff
@@ -367,10 +367,6 @@
|
||||
"category": "Error",
|
||||
"code": 1121
|
||||
},
|
||||
"A tuple type element list cannot be empty.": {
|
||||
"category": "Error",
|
||||
"code": 1122
|
||||
},
|
||||
"Variable declaration list cannot be empty.": {
|
||||
"category": "Error",
|
||||
"code": 1123
|
||||
@@ -847,6 +843,14 @@
|
||||
"category": "Error",
|
||||
"code": 1255
|
||||
},
|
||||
"A rest element must be last in a tuple type.": {
|
||||
"category": "Error",
|
||||
"code": 1256
|
||||
},
|
||||
"A required element cannot follow an optional element.": {
|
||||
"category": "Error",
|
||||
"code": 1257
|
||||
},
|
||||
"'with' statements are not allowed in an async function block.": {
|
||||
"category": "Error",
|
||||
"code": 1300
|
||||
@@ -2032,6 +2036,18 @@
|
||||
"category": "Error",
|
||||
"code": 2571
|
||||
},
|
||||
"Rest signatures are incompatible.": {
|
||||
"category": "Error",
|
||||
"code": 2572
|
||||
},
|
||||
"Property '{0}' is incompatible with rest element type.": {
|
||||
"category": "Error",
|
||||
"code": 2573
|
||||
},
|
||||
"A rest element type must be an array type.": {
|
||||
"category": "Error",
|
||||
"code": 2574
|
||||
},
|
||||
"JSX element attributes type '{0}' may not be a union type.": {
|
||||
"category": "Error",
|
||||
"code": 2600
|
||||
|
||||
+10
-2
@@ -659,6 +659,8 @@ namespace ts {
|
||||
return emitArrayType(<ArrayTypeNode>node);
|
||||
case SyntaxKind.TupleType:
|
||||
return emitTupleType(<TupleTypeNode>node);
|
||||
case SyntaxKind.OptionalType:
|
||||
return emitOptionalType(<OptionalTypeNode>node);
|
||||
case SyntaxKind.UnionType:
|
||||
return emitUnionType(<UnionTypeNode>node);
|
||||
case SyntaxKind.IntersectionType:
|
||||
@@ -695,8 +697,9 @@ namespace ts {
|
||||
return emitJSDocNonNullableType(node as JSDocNonNullableType);
|
||||
case SyntaxKind.JSDocOptionalType:
|
||||
return emitJSDocOptionalType(node as JSDocOptionalType);
|
||||
case SyntaxKind.RestType:
|
||||
case SyntaxKind.JSDocVariadicType:
|
||||
return emitJSDocVariadicType(node as JSDocVariadicType);
|
||||
return emitRestOrJSDocVariadicType(node as RestTypeNode | JSDocVariadicType);
|
||||
|
||||
// Binding patterns
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
@@ -1304,7 +1307,7 @@ namespace ts {
|
||||
writePunctuation("]");
|
||||
}
|
||||
|
||||
function emitJSDocVariadicType(node: JSDocVariadicType) {
|
||||
function emitRestOrJSDocVariadicType(node: RestTypeNode | JSDocVariadicType) {
|
||||
write("...");
|
||||
emit(node.type);
|
||||
}
|
||||
@@ -1315,6 +1318,11 @@ namespace ts {
|
||||
writePunctuation("]");
|
||||
}
|
||||
|
||||
function emitOptionalType(node: OptionalTypeNode) {
|
||||
emit(node.type);
|
||||
write("?");
|
||||
}
|
||||
|
||||
function emitUnionType(node: UnionTypeNode) {
|
||||
emitList(node, node.types, ListFormat.UnionTypeConstituents);
|
||||
}
|
||||
|
||||
+25
-1
@@ -745,12 +745,36 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function updateTypleTypeNode(node: TupleTypeNode, elementTypes: ReadonlyArray<TypeNode>) {
|
||||
export function updateTupleTypeNode(node: TupleTypeNode, elementTypes: ReadonlyArray<TypeNode>) {
|
||||
return node.elementTypes !== elementTypes
|
||||
? updateNode(createTupleTypeNode(elementTypes), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
export function createOptionalTypeNode(type: TypeNode) {
|
||||
const node = createSynthesizedNode(SyntaxKind.OptionalType) as OptionalTypeNode;
|
||||
node.type = parenthesizeArrayTypeMember(type);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function updateOptionalTypeNode(node: OptionalTypeNode, type: TypeNode): OptionalTypeNode {
|
||||
return node.type !== type
|
||||
? updateNode(createOptionalTypeNode(type), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
export function createRestTypeNode(type: TypeNode) {
|
||||
const node = createSynthesizedNode(SyntaxKind.RestType) as RestTypeNode;
|
||||
node.type = type;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function updateRestTypeNode(node: RestTypeNode, type: TypeNode): RestTypeNode {
|
||||
return node.type !== type
|
||||
? updateNode(createRestTypeNode(type), node)
|
||||
: node;
|
||||
}
|
||||
|
||||
export function createUnionTypeNode(types: ReadonlyArray<TypeNode>): UnionTypeNode {
|
||||
return <UnionTypeNode>createUnionOrIntersectionTypeNode(SyntaxKind.UnionType, types);
|
||||
}
|
||||
|
||||
+25
-13
@@ -445,19 +445,17 @@ namespace ts {
|
||||
case SyntaxKind.JsxClosingElement:
|
||||
return visitNode(cbNode, (<JsxClosingElement>node).tagName);
|
||||
|
||||
case SyntaxKind.OptionalType:
|
||||
case SyntaxKind.RestType:
|
||||
case SyntaxKind.JSDocTypeExpression:
|
||||
return visitNode(cbNode, (<JSDocTypeExpression>node).type);
|
||||
case SyntaxKind.JSDocNonNullableType:
|
||||
return visitNode(cbNode, (<JSDocNonNullableType>node).type);
|
||||
case SyntaxKind.JSDocNullableType:
|
||||
return visitNode(cbNode, (<JSDocNullableType>node).type);
|
||||
case SyntaxKind.JSDocOptionalType:
|
||||
return visitNode(cbNode, (<JSDocOptionalType>node).type);
|
||||
case SyntaxKind.JSDocVariadicType:
|
||||
return visitNode(cbNode, (<OptionalTypeNode | RestTypeNode | JSDocTypeExpression | JSDocTypeReferencingNode>node).type);
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
return visitNodes(cbNode, cbNodes, (<JSDocFunctionType>node).parameters) ||
|
||||
visitNode(cbNode, (<JSDocFunctionType>node).type);
|
||||
case SyntaxKind.JSDocVariadicType:
|
||||
return visitNode(cbNode, (<JSDocVariadicType>node).type);
|
||||
case SyntaxKind.JSDocComment:
|
||||
return visitNodes(cbNode, cbNodes, (<JSDoc>node).tags);
|
||||
case SyntaxKind.JSDocParameterTag:
|
||||
@@ -2289,7 +2287,7 @@ namespace ts {
|
||||
function parseJSDocAllType(postFixEquals: boolean): JSDocAllType | JSDocOptionalType {
|
||||
const result = createNode(SyntaxKind.JSDocAllType) as JSDocAllType;
|
||||
if (postFixEquals) {
|
||||
return createJSDocPostfixType(SyntaxKind.JSDocOptionalType, result) as JSDocOptionalType;
|
||||
return createPostfixType(SyntaxKind.JSDocOptionalType, result) as JSDocOptionalType;
|
||||
}
|
||||
else {
|
||||
nextToken();
|
||||
@@ -2367,7 +2365,7 @@ namespace ts {
|
||||
type = finishNode(variadic);
|
||||
}
|
||||
if (token() === SyntaxKind.EqualsToken) {
|
||||
return createJSDocPostfixType(SyntaxKind.JSDocOptionalType, type);
|
||||
return createPostfixType(SyntaxKind.JSDocOptionalType, type);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
@@ -2775,9 +2773,23 @@ namespace ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseTupleElementType() {
|
||||
const pos = getNodePos();
|
||||
if (parseOptional(SyntaxKind.DotDotDotToken)) {
|
||||
const node = <RestTypeNode>createNode(SyntaxKind.RestType, pos);
|
||||
node.type = parseType();
|
||||
return finishNode(node);
|
||||
}
|
||||
const type = parseType();
|
||||
if (!(contextFlags & NodeFlags.JSDoc) && type.kind === SyntaxKind.JSDocNullableType && type.pos === (<JSDocNullableType>type).type.pos) {
|
||||
type.kind = SyntaxKind.OptionalType;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function parseTupleType(): TupleTypeNode {
|
||||
const node = <TupleTypeNode>createNode(SyntaxKind.TupleType);
|
||||
node.elementTypes = parseBracketedList(ParsingContext.TupleElementTypes, parseType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
|
||||
node.elementTypes = parseBracketedList(ParsingContext.TupleElementTypes, parseTupleElementType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
@@ -2960,14 +2972,14 @@ namespace ts {
|
||||
while (!scanner.hasPrecedingLineBreak()) {
|
||||
switch (token()) {
|
||||
case SyntaxKind.ExclamationToken:
|
||||
type = createJSDocPostfixType(SyntaxKind.JSDocNonNullableType, type);
|
||||
type = createPostfixType(SyntaxKind.JSDocNonNullableType, type);
|
||||
break;
|
||||
case SyntaxKind.QuestionToken:
|
||||
// If not in JSDoc and next token is start of a type we have a conditional type
|
||||
if (!(contextFlags & NodeFlags.JSDoc) && lookAhead(nextTokenIsStartOfType)) {
|
||||
return type;
|
||||
}
|
||||
type = createJSDocPostfixType(SyntaxKind.JSDocNullableType, type);
|
||||
type = createPostfixType(SyntaxKind.JSDocNullableType, type);
|
||||
break;
|
||||
case SyntaxKind.OpenBracketToken:
|
||||
parseExpected(SyntaxKind.OpenBracketToken);
|
||||
@@ -2992,9 +3004,9 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
function createJSDocPostfixType(kind: SyntaxKind, type: TypeNode) {
|
||||
function createPostfixType(kind: SyntaxKind, type: TypeNode) {
|
||||
nextToken();
|
||||
const postfix = createNode(kind, type.pos) as JSDocOptionalType | JSDocNonNullableType | JSDocNullableType;
|
||||
const postfix = createNode(kind, type.pos) as OptionalTypeNode | JSDocOptionalType | JSDocNonNullableType | JSDocNullableType;
|
||||
postfix.type = type;
|
||||
return finishNode(postfix);
|
||||
}
|
||||
|
||||
@@ -380,6 +380,8 @@ namespace ts {
|
||||
|
||||
case SyntaxKind.ArrayType:
|
||||
case SyntaxKind.TupleType:
|
||||
case SyntaxKind.OptionalType:
|
||||
case SyntaxKind.RestType:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.TypePredicate:
|
||||
case SyntaxKind.TypeParameter:
|
||||
|
||||
+32
-2
@@ -225,6 +225,8 @@ namespace ts {
|
||||
TypeLiteral,
|
||||
ArrayType,
|
||||
TupleType,
|
||||
OptionalType,
|
||||
RestType,
|
||||
UnionType,
|
||||
IntersectionType,
|
||||
ConditionalType,
|
||||
@@ -269,6 +271,7 @@ namespace ts {
|
||||
AsExpression,
|
||||
NonNullExpression,
|
||||
MetaProperty,
|
||||
SyntheticExpression,
|
||||
|
||||
// Misc
|
||||
TemplateSpan,
|
||||
@@ -1101,6 +1104,16 @@ namespace ts {
|
||||
elementTypes: NodeArray<TypeNode>;
|
||||
}
|
||||
|
||||
export interface OptionalTypeNode extends TypeNode {
|
||||
kind: SyntaxKind.OptionalType;
|
||||
type: TypeNode;
|
||||
}
|
||||
|
||||
export interface RestTypeNode extends TypeNode {
|
||||
kind: SyntaxKind.RestType;
|
||||
type: TypeNode;
|
||||
}
|
||||
|
||||
export type UnionOrIntersectionTypeNode = UnionTypeNode | IntersectionTypeNode;
|
||||
|
||||
export interface UnionTypeNode extends TypeNode {
|
||||
@@ -1288,6 +1301,12 @@ namespace ts {
|
||||
expression?: Expression;
|
||||
}
|
||||
|
||||
export interface SyntheticExpression extends Expression {
|
||||
kind: SyntaxKind.SyntheticExpression;
|
||||
isSpread: boolean;
|
||||
type: Type;
|
||||
}
|
||||
|
||||
// see: https://tc39.github.io/ecma262/#prod-ExponentiationExpression
|
||||
export type ExponentiationOperator
|
||||
= SyntaxKind.AsteriskAsteriskToken
|
||||
@@ -3521,14 +3540,15 @@ namespace ts {
|
||||
ContainsPrivate = 1 << 8, // Synthetic property with private constituent(s)
|
||||
ContainsStatic = 1 << 9, // Synthetic property with static constituent(s)
|
||||
Late = 1 << 10, // Late-bound symbol for a computed property with a dynamic name
|
||||
ReverseMapped = 1 << 11, // property of reverse-inferred homomorphic mapped type.
|
||||
ReverseMapped = 1 << 11, // Property of reverse-inferred homomorphic mapped type
|
||||
OptionalParameter = 1 << 12, // Optional parameter
|
||||
RestParameter = 1 << 13, // Rest parameter
|
||||
Synthetic = SyntheticProperty | SyntheticMethod
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface TransientSymbol extends Symbol, SymbolLinks {
|
||||
checkFlags: CheckFlags;
|
||||
isRestParameter?: boolean;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -3857,6 +3877,16 @@ namespace ts {
|
||||
variances?: Variance[]; // Variance of each type parameter
|
||||
}
|
||||
|
||||
export interface TupleType extends GenericType {
|
||||
minLength: number;
|
||||
hasRestElement: boolean;
|
||||
associatedNames?: __String[];
|
||||
}
|
||||
|
||||
export interface TupleTypeReference extends TypeReference {
|
||||
target: TupleType;
|
||||
}
|
||||
|
||||
export interface UnionOrIntersectionType extends Type {
|
||||
types: Type[]; // Constituent types
|
||||
/* @internal */
|
||||
|
||||
@@ -372,9 +372,17 @@ namespace ts {
|
||||
visitNode((<ArrayTypeNode>node).elementType, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.TupleType:
|
||||
return updateTypleTypeNode((<TupleTypeNode>node),
|
||||
return updateTupleTypeNode((<TupleTypeNode>node),
|
||||
nodesVisitor((<TupleTypeNode>node).elementTypes, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.OptionalType:
|
||||
return updateOptionalTypeNode((<OptionalTypeNode>node),
|
||||
visitNode((<OptionalTypeNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.RestType:
|
||||
return updateRestTypeNode((<RestTypeNode>node),
|
||||
visitNode((<RestTypeNode>node).type, visitor, isTypeNode));
|
||||
|
||||
case SyntaxKind.UnionType:
|
||||
return updateUnionTypeNode(<UnionTypeNode>node,
|
||||
nodesVisitor((<UnionTypeNode>node).types, visitor, isTypeNode));
|
||||
|
||||
Reference in New Issue
Block a user