Skip to content

Commit 2e04322

Browse files
committed
Optional elements in tuple types + empty tuple types + other fixes.
1 parent 43bfccf commit 2e04322

9 files changed

Lines changed: 204 additions & 157 deletions

File tree

src/compiler/binder.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3601,6 +3601,7 @@ namespace ts {
36013601
case SyntaxKind.TypeLiteral:
36023602
case SyntaxKind.ArrayType:
36033603
case SyntaxKind.TupleType:
3604+
case SyntaxKind.OptionalType:
36043605
case SyntaxKind.UnionType:
36053606
case SyntaxKind.IntersectionType:
36063607
case SyntaxKind.ConditionalType:

src/compiler/checker.ts

Lines changed: 149 additions & 138 deletions
Large diffs are not rendered by default.

src/compiler/diagnosticMessages.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -367,10 +367,6 @@
367367
"category": "Error",
368368
"code": 1121
369369
},
370-
"A tuple type element list cannot be empty.": {
371-
"category": "Error",
372-
"code": 1122
373-
},
374370
"Variable declaration list cannot be empty.": {
375371
"category": "Error",
376372
"code": 1123

src/compiler/emitter.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,8 @@ namespace ts {
640640
return emitArrayType(<ArrayTypeNode>node);
641641
case SyntaxKind.TupleType:
642642
return emitTupleType(<TupleTypeNode>node);
643+
case SyntaxKind.OptionalType:
644+
return emitOptionalType(<OptionalTypeNode>node);
643645
case SyntaxKind.UnionType:
644646
return emitUnionType(<UnionTypeNode>node);
645647
case SyntaxKind.IntersectionType:
@@ -1296,6 +1298,11 @@ namespace ts {
12961298
writePunctuation("]");
12971299
}
12981300

1301+
function emitOptionalType(node: OptionalTypeNode) {
1302+
emit(node.type);
1303+
write("?");
1304+
}
1305+
12991306
function emitUnionType(node: UnionTypeNode) {
13001307
emitList(node, node.types, ListFormat.UnionTypeConstituents);
13011308
}

src/compiler/factory.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -745,12 +745,24 @@ namespace ts {
745745
return node;
746746
}
747747

748-
export function updateTypleTypeNode(node: TupleTypeNode, elementTypes: ReadonlyArray<TypeNode>) {
748+
export function updateTupleTypeNode(node: TupleTypeNode, elementTypes: ReadonlyArray<TypeNode>) {
749749
return node.elementTypes !== elementTypes
750750
? updateNode(createTupleTypeNode(elementTypes), node)
751751
: node;
752752
}
753753

754+
export function createOptionalTypeNode(type: TypeNode) {
755+
const node = createSynthesizedNode(SyntaxKind.OptionalType) as OptionalTypeNode;
756+
node.type = parenthesizeArrayTypeMember(type);
757+
return node;
758+
}
759+
760+
export function updateOptionalTypeNode(node: OptionalTypeNode, type: TypeNode): OptionalTypeNode {
761+
return node.type !== type
762+
? updateNode(createOptionalTypeNode(type), node)
763+
: node;
764+
}
765+
754766
export function createUnionTypeNode(types: ReadonlyArray<TypeNode>): UnionTypeNode {
755767
return <UnionTypeNode>createUnionOrIntersectionTypeNode(SyntaxKind.UnionType, types);
756768
}

src/compiler/parser.ts

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -446,19 +446,16 @@ namespace ts {
446446
case SyntaxKind.JsxClosingElement:
447447
return visitNode(cbNode, (<JsxClosingElement>node).tagName);
448448

449+
case SyntaxKind.OptionalType:
449450
case SyntaxKind.JSDocTypeExpression:
450-
return visitNode(cbNode, (<JSDocTypeExpression>node).type);
451451
case SyntaxKind.JSDocNonNullableType:
452-
return visitNode(cbNode, (<JSDocNonNullableType>node).type);
453452
case SyntaxKind.JSDocNullableType:
454-
return visitNode(cbNode, (<JSDocNullableType>node).type);
455453
case SyntaxKind.JSDocOptionalType:
456-
return visitNode(cbNode, (<JSDocOptionalType>node).type);
454+
case SyntaxKind.JSDocVariadicType:
455+
return visitNode(cbNode, (<OptionalTypeNode | JSDocTypeExpression | JSDocTypeReferencingNode>node).type);
457456
case SyntaxKind.JSDocFunctionType:
458457
return visitNodes(cbNode, cbNodes, (<JSDocFunctionType>node).parameters) ||
459458
visitNode(cbNode, (<JSDocFunctionType>node).type);
460-
case SyntaxKind.JSDocVariadicType:
461-
return visitNode(cbNode, (<JSDocVariadicType>node).type);
462459
case SyntaxKind.JSDocComment:
463460
return visitNodes(cbNode, cbNodes, (<JSDoc>node).tags);
464461
case SyntaxKind.JSDocParameterTag:
@@ -2274,7 +2271,7 @@ namespace ts {
22742271
function parseJSDocAllType(postFixEquals: boolean): JSDocAllType | JSDocOptionalType {
22752272
const result = createNode(SyntaxKind.JSDocAllType) as JSDocAllType;
22762273
if (postFixEquals) {
2277-
return createJSDocPostfixType(SyntaxKind.JSDocOptionalType, result) as JSDocOptionalType;
2274+
return createPostfixType(SyntaxKind.JSDocOptionalType, result) as JSDocOptionalType;
22782275
}
22792276
else {
22802277
nextToken();
@@ -2352,7 +2349,7 @@ namespace ts {
23522349
type = finishNode(variadic);
23532350
}
23542351
if (token() === SyntaxKind.EqualsToken) {
2355-
return createJSDocPostfixType(SyntaxKind.JSDocOptionalType, type);
2352+
return createPostfixType(SyntaxKind.JSDocOptionalType, type);
23562353
}
23572354
return type;
23582355
}
@@ -2766,9 +2763,17 @@ namespace ts {
27662763
return finishNode(node);
27672764
}
27682765

2766+
function parseTupleElementType() {
2767+
const type = parseType();
2768+
if (!(contextFlags & NodeFlags.JSDoc) && type.kind === SyntaxKind.JSDocNullableType && type.pos === (<JSDocNullableType>type).type.pos) {
2769+
type.kind = SyntaxKind.OptionalType;
2770+
}
2771+
return type;
2772+
}
2773+
27692774
function parseTupleType(): TupleTypeNode {
27702775
const node = <TupleTypeNode>createNode(SyntaxKind.TupleType);
2771-
node.elementTypes = parseBracketedList(ParsingContext.TupleElementTypes, parseType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
2776+
node.elementTypes = parseBracketedList(ParsingContext.TupleElementTypes, parseTupleElementType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
27722777
return finishNode(node);
27732778
}
27742779

@@ -2960,14 +2965,14 @@ namespace ts {
29602965
while (!scanner.hasPrecedingLineBreak()) {
29612966
switch (token()) {
29622967
case SyntaxKind.ExclamationToken:
2963-
type = createJSDocPostfixType(SyntaxKind.JSDocNonNullableType, type);
2968+
type = createPostfixType(SyntaxKind.JSDocNonNullableType, type);
29642969
break;
29652970
case SyntaxKind.QuestionToken:
29662971
// If not in JSDoc and next token is start of a type we have a conditional type
29672972
if (!(contextFlags & NodeFlags.JSDoc) && lookAhead(nextTokenIsStartOfType)) {
29682973
return type;
29692974
}
2970-
type = createJSDocPostfixType(SyntaxKind.JSDocNullableType, type);
2975+
type = createPostfixType(SyntaxKind.JSDocNullableType, type);
29712976
break;
29722977
case SyntaxKind.OpenBracketToken:
29732978
parseExpected(SyntaxKind.OpenBracketToken);
@@ -2992,9 +2997,9 @@ namespace ts {
29922997
return type;
29932998
}
29942999

2995-
function createJSDocPostfixType(kind: SyntaxKind, type: TypeNode) {
3000+
function createPostfixType(kind: SyntaxKind, type: TypeNode) {
29963001
nextToken();
2997-
const postfix = createNode(kind, type.pos) as JSDocOptionalType | JSDocNonNullableType | JSDocNullableType;
3002+
const postfix = createNode(kind, type.pos) as OptionalTypeNode | JSDocOptionalType | JSDocNonNullableType | JSDocNullableType;
29983003
postfix.type = type;
29993004
return finishNode(postfix);
30003005
}

src/compiler/transformers/ts.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ namespace ts {
380380

381381
case SyntaxKind.ArrayType:
382382
case SyntaxKind.TupleType:
383+
case SyntaxKind.OptionalType:
383384
case SyntaxKind.TypeLiteral:
384385
case SyntaxKind.TypePredicate:
385386
case SyntaxKind.TypeParameter:

src/compiler/types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ namespace ts {
275275
TypeLiteral,
276276
ArrayType,
277277
TupleType,
278+
OptionalType,
278279
UnionType,
279280
IntersectionType,
280281
ConditionalType,
@@ -1145,6 +1146,11 @@ namespace ts {
11451146
elementTypes: NodeArray<TypeNode>;
11461147
}
11471148

1149+
export interface OptionalTypeNode extends TypeNode {
1150+
kind: SyntaxKind.OptionalType;
1151+
type: TypeNode;
1152+
}
1153+
11481154
export type UnionOrIntersectionTypeNode = UnionTypeNode | IntersectionTypeNode;
11491155

11501156
export interface UnionTypeNode extends TypeNode {
@@ -3885,6 +3891,10 @@ namespace ts {
38853891
variances?: Variance[]; // Variance of each type parameter
38863892
}
38873893

3894+
export interface TupleType extends GenericType {
3895+
minLength: number;
3896+
}
3897+
38883898
export interface UnionOrIntersectionType extends Type {
38893899
types: Type[]; // Constituent types
38903900
/* @internal */

src/compiler/visitor.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,9 +372,13 @@ namespace ts {
372372
visitNode((<ArrayTypeNode>node).elementType, visitor, isTypeNode));
373373

374374
case SyntaxKind.TupleType:
375-
return updateTypleTypeNode((<TupleTypeNode>node),
375+
return updateTupleTypeNode((<TupleTypeNode>node),
376376
nodesVisitor((<TupleTypeNode>node).elementTypes, visitor, isTypeNode));
377377

378+
case SyntaxKind.OptionalType:
379+
return updateOptionalTypeNode((<OptionalTypeNode>node),
380+
visitNode((<OptionalTypeNode>node).type, visitor, isTypeNode));
381+
378382
case SyntaxKind.UnionType:
379383
return updateUnionTypeNode(<UnionTypeNode>node,
380384
nodesVisitor((<UnionTypeNode>node).types, visitor, isTypeNode));

0 commit comments

Comments
 (0)