Initial support for 'match' type

This commit is contained in:
Ron Buckton
2017-09-02 21:06:10 -07:00
parent 541920eb31
commit 06e46fbde6
11 changed files with 441 additions and 10 deletions
+4
View File
@@ -3367,6 +3367,10 @@ namespace ts {
case SyntaxKind.TypeOperator:
case SyntaxKind.IndexedAccessType:
case SyntaxKind.MappedType:
case SyntaxKind.MatchType:
case SyntaxKind.MatchTypeBlock:
case SyntaxKind.MatchTypeMatchClause:
case SyntaxKind.MatchTypeElseClause:
case SyntaxKind.LiteralType:
case SyntaxKind.NamespaceExportDeclaration:
// Types and signatures are TypeScript syntax, and exclude all other facts.
+158
View File
@@ -2534,6 +2534,17 @@ namespace ts {
const indexTypeNode = typeToTypeNodeHelper((<IndexedAccessType>type).indexType, context);
return createIndexedAccessTypeNode(objectTypeNode, indexTypeNode);
}
if (type.flags & TypeFlags.Match) {
const typeArgument = typeToTypeNodeHelper((<MatchType>type).typeArgument, context);
const clauses: MatchTypeMatchOrElseClause[] = map((<MatchType>type).clauses, clause => {
const matchType = typeToTypeNodeHelper(clause.matchType, context);
const resultType = typeToTypeNodeHelper(clause.resultType, context);
return createMatchTypeMatchClause(matchType, resultType);
});
const elseType = (<MatchType>type).elseType;
if (elseType) clauses.push(createMatchTypeElseClause(typeToTypeNodeHelper(elseType, context)));
return createMatchTypeNode(typeArgument, createMatchTypeBlock(clauses));
}
Debug.fail("Should be unreachable.");
@@ -3303,6 +3314,9 @@ namespace ts {
writeType((<IndexedAccessType>type).indexType, TypeFormatFlags.None);
writePunctuation(writer, SyntaxKind.CloseBracketToken);
}
else if (type.flags & TypeFlags.Match) {
writeMatchType(<MatchType>type);
}
else {
// Should never get here
// { ... }
@@ -3314,6 +3328,35 @@ namespace ts {
}
}
function writeMatchType(type: MatchType) {
writeType((<MatchType>type).typeArgument, TypeFormatFlags.None);
writeSpace(writer);
writer.writeKeyword("match");
writeSpace(writer);
writePunctuation(writer, SyntaxKind.OpenBracketToken);
writer.writeLine();
writer.increaseIndent();
for (const clause of (<MatchType>type).clauses) {
writeType(clause.matchType, TypeFormatFlags.None);
writePunctuation(writer, SyntaxKind.ColonToken);
writeSpace(writer);
writeType(clause.resultType, TypeFormatFlags.None);
writePunctuation(writer, SyntaxKind.CommaToken);
writer.writeLine();
}
const elseType = (<MatchType>type).elseType;
if (elseType) {
writer.writeKeyword("else");
writePunctuation(writer, SyntaxKind.ColonToken);
writeSpace(writer);
writeType(elseType, TypeFormatFlags.None);
writePunctuation(writer, SyntaxKind.CommaToken);
writer.writeLine();
}
writer.decreaseIndent();
writer.writeLine();
writePunctuation(writer, SyntaxKind.CloseBracketToken);
}
function writeTypeList(types: Type[], delimiter: SyntaxKind) {
for (let i = 0; i < types.length; i++) {
@@ -7730,6 +7773,65 @@ namespace ts {
return links.resolvedType;
}
function isGenericMatchTypeClause(clause: MatchTypeClause): boolean {
return isGenericObjectType(clause.matchType);
}
function getMatchTypeConstituents(type: MatchType) {
if (type.clauses.length === 0) return type.elseType || neverType;
const constituents: Type[] = [];
for (const clause of type.clauses) {
constituents.push(clause.resultType);
}
if (type.elseType) {
constituents.push(type.elseType);
}
return getUnionType(constituents);
}
function getMatchType(typeArgument: Type, clauses: ReadonlyArray<MatchTypeClause>, elseType: Type | undefined, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]) {
if (clauses.length > 0 && (isGenericObjectType(typeArgument) || forEach(clauses, isGenericMatchTypeClause))) {
if (clauses.length > 0) {
const type = <MatchType>createType(TypeFlags.Match);
type.typeArgument = typeArgument;
type.clauses = clauses;
type.elseType = elseType;
type.aliasSymbol = aliasSymbol;
type.aliasTypeArguments = aliasTypeArguments;
return type;
}
}
for (const clause of clauses) {
if (isTypeAssignableTo(typeArgument, clause.matchType)) {
return clause.resultType;
}
}
return elseType || neverType;
}
function getTypeFromMatchTypeNode(node: MatchTypeNode) {
const links = getNodeLinks(node);
if (!links.resolvedType) {
const typeArgument = getTypeFromTypeNode(node.typeArgument);
const clauses: MatchTypeClause[] = [];
let elseType: Type | undefined;
for (const clause of node.matchBlock.clauses) {
if (clause.kind === SyntaxKind.MatchTypeElseClause) {
if (!elseType) elseType = getTypeFromTypeNode(clause.resultType);
}
else {
const matchType = getTypeFromTypeNode(clause.matchType);
const resultType = getTypeFromTypeNode(clause.resultType);
clauses.push({ matchType, resultType });
}
}
links.resolvedType = getMatchType(typeArgument, clauses, elseType, getAliasSymbolForTypeNode(node), getAliasTypeArgumentsForTypeNode(node));
}
return links.resolvedType;
}
function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: TypeNode): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
@@ -7992,6 +8094,8 @@ namespace ts {
return getTypeFromIndexedAccessTypeNode(<IndexedAccessTypeNode>node);
case SyntaxKind.MappedType:
return getTypeFromMappedTypeNode(<MappedTypeNode>node);
case SyntaxKind.MatchType:
return getTypeFromMatchTypeNode(<MatchTypeNode>node);
// This function assumes that an identifier or qualified name is a type expression
// Callers should first ensure this by calling isTypeNode
case SyntaxKind.Identifier:
@@ -8005,6 +8109,8 @@ namespace ts {
}
}
function instantiateList<T>(items: T[], mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): T[];
function instantiateList<T>(items: ReadonlyArray<T>, mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): ReadonlyArray<T>;
function instantiateList<T>(items: T[], mapper: TypeMapper, instantiator: (item: T, mapper: TypeMapper) => T): T[] {
if (items && items.length) {
const result: T[] = [];
@@ -8356,9 +8462,23 @@ namespace ts {
if (type.flags & TypeFlags.IndexedAccess) {
return getIndexedAccessType(instantiateType((<IndexedAccessType>type).objectType, mapper), instantiateType((<IndexedAccessType>type).indexType, mapper));
}
if (type.flags & TypeFlags.Match) {
return getMatchType(
instantiateType((<MatchType>type).typeArgument, mapper),
instantiateList((<MatchType>type).clauses, mapper, instantiateMatchTypeClause),
instantiateType((<MatchType>type).elseType, mapper),
type.aliasSymbol,
instantiateTypes(type.aliasTypeArguments, mapper));
}
return type;
}
function instantiateMatchTypeClause(clause: MatchTypeClause, mapper: TypeMapper) {
const matchType = instantiateType(clause.matchType, mapper);
const resultType = instantiateType(clause.resultType, mapper);
return { matchType, resultType };
}
function instantiateIndexInfo(info: IndexInfo, mapper: TypeMapper): IndexInfo {
return info && createIndexInfo(instantiateType(info.type, mapper), info.isReadonly, info.declaration);
}
@@ -9362,6 +9482,14 @@ namespace ts {
}
}
else {
if (source.flags & TypeFlags.Match) {
if (target.flags & TypeFlags.Union) {
if (result = isRelatedTo(getMatchTypeConstituents(<MatchType>source), target, reportErrors)) {
errorInfo = saveErrorInfo;
return result;
}
}
}
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
// We have type references to same target type, see if relationship holds for all type arguments
if (result = typeArgumentsRelatedTo(<TypeReference>source, <TypeReference>target, reportErrors)) {
@@ -18879,6 +19007,34 @@ namespace ts {
checkTypeAssignableTo(constraintType, stringType, node.typeParameter.constraint);
}
function checkMatchType(node: MatchTypeNode) {
checkSourceElement(node.typeArgument);
let firstElseClause: MatchTypeElseClause;
let hasDuplicateElseClause = false;
for (const clause of node.matchBlock.clauses) {
if (clause.kind === SyntaxKind.MatchTypeElseClause) {
if (hasDuplicateElseClause) continue;
if (!firstElseClause) {
firstElseClause = clause;
}
else {
const sourceFile = getSourceFileOfNode(node);
const start = skipTrivia(sourceFile.text, clause.pos);
const end = clause.resultType ? clause.resultType.pos : clause.end;
grammarErrorAtPos(sourceFile, start, end - start, Diagnostics.An_else_clause_cannot_appear_more_than_once_in_a_match_type);
hasDuplicateElseClause = true;
}
}
else {
checkSourceElement(clause.matchType);
}
checkSourceElement(clause.resultType);
}
}
function isPrivateWithinAmbient(node: Node): boolean {
return hasModifier(node, ModifierFlags.Private) && isInAmbientContext(node);
}
@@ -22412,6 +22568,8 @@ namespace ts {
return checkIndexedAccessType(<IndexedAccessTypeNode>node);
case SyntaxKind.MappedType:
return checkMappedType(<MappedTypeNode>node);
case SyntaxKind.MatchType:
return checkMatchType(<MatchTypeNode>node);
case SyntaxKind.FunctionDeclaration:
return checkFunctionDeclaration(<FunctionDeclaration>node);
case SyntaxKind.Block:
+31
View File
@@ -447,6 +447,8 @@ namespace ts {
return emitIndexedAccessType(<IndexedAccessTypeNode>type);
case SyntaxKind.MappedType:
return emitMappedType(<MappedTypeNode>type);
case SyntaxKind.MatchType:
return emitMatchType(<MatchTypeNode>type);
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
return emitSignatureDeclarationWithJsDocComments(<FunctionOrConstructorTypeNode>type);
@@ -579,6 +581,18 @@ namespace ts {
enclosingDeclaration = prevEnclosingDeclaration;
}
function emitMatchType(node: MatchTypeNode) {
emitType(node.typeArgument);
write(" match {");
if (node.matchBlock.clauses.length) {
increaseIndent();
emitCommaList(node.matchBlock.clauses, emitNode);
writeLine();
decreaseIndent();
}
write("}");
}
function emitTypeLiteral(type: TypeLiteralNode) {
write("{");
if (type.members.length) {
@@ -1808,6 +1822,19 @@ namespace ts {
}
}
function emitMatchTypeMatchClause(node: MatchTypeMatchClause) {
writeLine();
emitType(node.matchType);
write(": ");
emitType(node.resultType);
}
function emitMatchTypeElseClause(node: MatchTypeElseClause) {
writeLine();
write("else: ");
emitType(node.resultType);
}
function emitNode(node: Node) {
switch (node.kind) {
case SyntaxKind.FunctionDeclaration:
@@ -1841,6 +1868,10 @@ namespace ts {
return emitPropertyDeclaration(<PropertyDeclaration>node);
case SyntaxKind.EnumMember:
return emitEnumMemberDeclaration(<EnumMember>node);
case SyntaxKind.MatchTypeMatchClause:
return emitMatchTypeMatchClause(<MatchTypeMatchClause>node);
case SyntaxKind.MatchTypeElseClause:
return emitMatchTypeElseClause(<MatchTypeElseClause>node);
case SyntaxKind.ExportAssignment:
return emitExportAssignment(<ExportAssignment>node);
case SyntaxKind.SourceFile:
+8
View File
@@ -907,6 +907,14 @@
"category": "Error",
"code": 1328
},
"Type or 'else' expected.": {
"category": "Error",
"code": 1329
},
"An 'else' clause cannot appear more than once in a 'match' type.": {
"category": "Error",
"code": 1330
},
"Duplicate identifier '{0}'.": {
"category": "Error",
+34
View File
@@ -557,6 +557,15 @@ namespace ts {
return emitIndexedAccessType(<IndexedAccessTypeNode>node);
case SyntaxKind.MappedType:
return emitMappedType(<MappedTypeNode>node);
case SyntaxKind.MatchType:
return emitMatchType(<MatchTypeNode>node);
case SyntaxKind.MatchTypeBlock:
return emitMatchTypeBlock(<MatchTypeBlock>node);
case SyntaxKind.MatchTypeMatchClause:
return emitMatchTypeMatchClause(<MatchTypeMatchClause>node);
case SyntaxKind.MatchTypeElseClause:
return emitMatchTypeElseClause(<MatchTypeElseClause>node);
case SyntaxKind.LiteralType:
return emitLiteralType(<LiteralTypeNode>node);
@@ -1114,6 +1123,30 @@ namespace ts {
write("}");
}
function emitMatchType(node: MatchTypeNode) {
emit(node.typeArgument);
writeToken(SyntaxKind.MatchKeyword, node.typeArgument.end);
write(" ");
emit(node.matchBlock);
}
function emitMatchTypeBlock(node: MatchTypeBlock) {
writeToken(SyntaxKind.OpenBraceToken, node.pos);
emitList(node, node.clauses, ListFormat.MatchTypeBlockClauses);
writeToken(SyntaxKind.CloseBraceToken, node.clauses.end);
}
function emitMatchTypeMatchClause(node: MatchTypeMatchClause) {
emit(node.matchType);
write(": ");
emit(node.resultType);
}
function emitMatchTypeElseClause(node: MatchTypeElseClause) {
write("else: ");
emit(node.resultType);
}
function emitLiteralType(node: LiteralTypeNode) {
emitExpression(node.literal);
}
@@ -3134,6 +3167,7 @@ namespace ts {
InterfaceMembers = Indented | MultiLine,
EnumMembers = CommaDelimited | Indented | MultiLine,
CaseBlockClauses = Indented | MultiLine,
MatchTypeBlockClauses = Indented | MultiLine | CommaDelimited | AllowTrailingComma,
NamedImportsOrExportsElements = CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | SingleLine | SpaceBetweenBraces,
JsxElementChildren = SingleLine | NoInterveningComments,
JsxElementAttributes = SingleLine | SpaceBetweenSiblings | NoInterveningComments,
+52
View File
@@ -773,6 +773,58 @@ namespace ts {
: node;
}
export function createMatchTypeNode(typeArgument: TypeNode, matchBlock: MatchTypeBlock) {
const node = createSynthesizedNode(SyntaxKind.MatchType) as MatchTypeNode;
node.typeArgument = typeArgument;
node.matchBlock = matchBlock;
return node;
}
export function updateMatchTypeNode(node: MatchTypeNode, typeArgument: TypeNode, matchBlock: MatchTypeBlock) {
return node.typeArgument !== typeArgument
|| node.matchBlock !== matchBlock
? updateNode(createMatchTypeNode(typeArgument, matchBlock), node)
: node;
}
export function createMatchTypeBlock(clauses: ReadonlyArray<MatchTypeMatchOrElseClause>) {
const node = createSynthesizedNode(SyntaxKind.MatchTypeBlock) as MatchTypeBlock;
node.clauses = createNodeArray(clauses);
return node;
}
export function updateMatchTypeBlock(node: MatchTypeBlock, clauses: ReadonlyArray<MatchTypeMatchOrElseClause>) {
return node.clauses !== clauses
? updateNode(createMatchTypeBlock(clauses), node)
: node;
}
export function createMatchTypeMatchClause(matchType: TypeNode, resultType: TypeNode) {
const node = createSynthesizedNode(SyntaxKind.MatchTypeMatchClause) as MatchTypeMatchClause;
node.matchType = matchType;
node.resultType = resultType;
return node;
}
export function updateMatchTypeMatchClause(node: MatchTypeMatchClause, matchType: TypeNode, resultType: TypeNode) {
return node.matchType !== matchType
|| node.resultType !== resultType
? updateNode(createMatchTypeMatchClause(matchType, resultType), node)
: node;
}
export function createMatchTypeElseClause(resultType: TypeNode) {
const node = createSynthesizedNode(SyntaxKind.MatchTypeElseClause) as MatchTypeElseClause;
node.resultType = resultType;
return node;
}
export function updateMatchTypeElseClause(node: MatchTypeElseClause, resultType: TypeNode) {
return node.resultType !== resultType
? updateNode(createMatchTypeElseClause(resultType), node)
: node;
}
export function createLiteralTypeNode(literal: Expression) {
const node = createSynthesizedNode(SyntaxKind.LiteralType) as LiteralTypeNode;
node.literal = literal;
+72
View File
@@ -155,6 +155,16 @@ namespace ts {
visitNode(cbNode, (<MappedTypeNode>node).typeParameter) ||
visitNode(cbNode, (<MappedTypeNode>node).questionToken) ||
visitNode(cbNode, (<MappedTypeNode>node).type);
case SyntaxKind.MatchType:
return visitNode(cbNode, (<MatchTypeNode>node).typeArgument) ||
visitNode(cbNode, (<MatchTypeNode>node).matchBlock);
case SyntaxKind.MatchTypeBlock:
return visitNodes(cbNode, cbNodes, (<MatchTypeBlock>node).clauses);
case SyntaxKind.MatchTypeMatchClause:
return visitNode(cbNode, (<MatchTypeMatchClause>node).matchType) ||
visitNode(cbNode, (<MatchTypeMatchClause>node).resultType);
case SyntaxKind.MatchTypeElseClause:
return visitNode(cbNode, (<MatchTypeElseClause>node).resultType);
case SyntaxKind.LiteralType:
return visitNode(cbNode, (<LiteralTypeNode>node).literal);
case SyntaxKind.ObjectBindingPattern:
@@ -1332,6 +1342,8 @@ namespace ts {
return !(token() === SyntaxKind.SemicolonToken && inErrorRecovery) && isStartOfStatement();
case ParsingContext.SwitchClauses:
return token() === SyntaxKind.CaseKeyword || token() === SyntaxKind.DefaultKeyword;
case ParsingContext.MatchTypeClauses:
return token() === SyntaxKind.ElseKeyword || token() === SyntaxKind.CommaToken || isStartOfType();
case ParsingContext.TypeMembers:
return lookAhead(isTypeMemberStart);
case ParsingContext.ClassMembers:
@@ -1446,6 +1458,7 @@ namespace ts {
switch (kind) {
case ParsingContext.BlockStatements:
case ParsingContext.SwitchClauses:
case ParsingContext.MatchTypeClauses:
case ParsingContext.TypeMembers:
case ParsingContext.ClassMembers:
case ParsingContext.EnumMembers:
@@ -1631,6 +1644,9 @@ namespace ts {
case ParsingContext.SwitchClauses:
return isReusableSwitchClause(node);
case ParsingContext.MatchTypeClauses:
return isReusableMatchTypeClause(node);
case ParsingContext.SourceElements:
case ParsingContext.BlockStatements:
case ParsingContext.SwitchClauseStatements:
@@ -1740,6 +1756,17 @@ namespace ts {
return false;
}
function isReusableMatchTypeClause(node: Node) {
if (node) {
switch (node.kind) {
case SyntaxKind.MatchTypeMatchClause:
case SyntaxKind.MatchTypeElseClause:
return true;
}
}
return false;
}
function isReusableStatement(node: Node) {
if (node) {
switch (node.kind) {
@@ -1848,6 +1875,7 @@ namespace ts {
case ParsingContext.BlockStatements: return Diagnostics.Declaration_or_statement_expected;
case ParsingContext.SwitchClauses: return Diagnostics.case_or_default_expected;
case ParsingContext.SwitchClauseStatements: return Diagnostics.Statement_expected;
case ParsingContext.MatchTypeClauses: return Diagnostics.Type_or_else_expected;
case ParsingContext.RestProperties: // fallthrough
case ParsingContext.TypeMembers: return Diagnostics.Property_or_signature_expected;
case ParsingContext.ClassMembers: return Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected;
@@ -2585,6 +2613,45 @@ namespace ts {
return finishNode(node);
}
function parseMatchTypeMatchClause() {
const node = <MatchTypeMatchClause>createNode(SyntaxKind.MatchTypeMatchClause);
node.matchType = parseType();
parseExpected(SyntaxKind.ColonToken);
node.resultType = parseType();
return finishNode(node);
}
function parseMatchTypeElseClause() {
const node = <MatchTypeElseClause>createNode(SyntaxKind.MatchTypeElseClause);
parseExpected(SyntaxKind.ElseKeyword);
parseExpected(SyntaxKind.ColonToken);
node.resultType = parseType();
return finishNode(node);
}
function parseMatchTypeCaseOrElseClause(): MatchTypeMatchOrElseClause {
return token() === SyntaxKind.ElseKeyword ? parseMatchTypeElseClause() : parseMatchTypeMatchClause();
}
function parseMatchTypeRest(type: TypeNode) {
while (true) {
type = parseArrayTypeRest(type);
if (!scanner.hasPrecedingLineBreak() && token() === SyntaxKind.MatchKeyword) {
const node = <MatchTypeNode>createNode(SyntaxKind.MatchType, type.pos);
node.typeArgument = type;
parseExpected(SyntaxKind.MatchKeyword);
const matchBlock = <MatchTypeBlock>createNode(SyntaxKind.MatchTypeBlock);
parseExpected(SyntaxKind.OpenBraceToken);
matchBlock.clauses = parseDelimitedList(ParsingContext.MatchTypeClauses, parseMatchTypeCaseOrElseClause, /*considerSemicolonAsDelimiter*/ true);
parseExpected(SyntaxKind.CloseBraceToken);
node.matchBlock = finishNode(matchBlock);
type = finishNode(node);
continue;
}
return type;
}
}
function parseTupleType(): TupleTypeNode {
const node = <TupleTypeNode>createNode(SyntaxKind.TupleType);
node.elementTypes = parseBracketedList(ParsingContext.TupleElementTypes, parseType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
@@ -2768,6 +2835,10 @@ namespace ts {
function parseArrayTypeOrHigher(): TypeNode {
let type = parseJSDocPostfixTypeOrHigher();
return parseMatchTypeRest(type);
}
function parseArrayTypeRest(type: TypeNode): TypeNode {
while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) {
if (isStartOfType()) {
const node = <IndexedAccessTypeNode>createNode(SyntaxKind.IndexedAccessType, type.pos);
@@ -6118,6 +6189,7 @@ namespace ts {
BlockStatements, // Statements in block
SwitchClauses, // Clauses in switch statement
SwitchClauseStatements, // Statements in switch clause
MatchTypeClauses, // Clauses in a match type block
TypeMembers, // Members in interface or type literal
ClassMembers, // Members in class declaration
EnumMembers, // Members in enum declaration
+1
View File
@@ -94,6 +94,7 @@ namespace ts {
"is": SyntaxKind.IsKeyword,
"keyof": SyntaxKind.KeyOfKeyword,
"let": SyntaxKind.LetKeyword,
"match": SyntaxKind.MatchKeyword,
"module": SyntaxKind.ModuleKeyword,
"namespace": SyntaxKind.NamespaceKeyword,
"never": SyntaxKind.NeverKeyword,
+53 -9
View File
@@ -187,6 +187,7 @@ namespace ts {
GetKeyword,
IsKeyword,
KeyOfKeyword,
MatchKeyword,
ModuleKeyword,
NamespaceKeyword,
NeverKeyword,
@@ -239,6 +240,10 @@ namespace ts {
TypeOperator,
IndexedAccessType,
MappedType,
MatchType,
MatchTypeBlock,
MatchTypeMatchClause,
MatchTypeElseClause,
LiteralType,
// Binding patterns
ObjectBindingPattern,
@@ -1005,6 +1010,32 @@ namespace ts {
type?: TypeNode;
}
export interface MatchTypeNode extends TypeNode {
kind: SyntaxKind.MatchType;
typeArgument: TypeNode;
matchBlock: MatchTypeBlock;
}
export interface MatchTypeBlock extends Node {
kind: SyntaxKind.MatchTypeBlock;
clauses: NodeArray<MatchTypeMatchOrElseClause>;
}
export type MatchTypeMatchOrElseClause =
| MatchTypeMatchClause
| MatchTypeElseClause;
export interface MatchTypeMatchClause extends Node {
kind: SyntaxKind.MatchTypeMatchClause;
matchType: TypeNode;
resultType: TypeNode;
}
export interface MatchTypeElseClause extends Node {
kind: SyntaxKind.MatchTypeElseClause;
resultType: TypeNode;
}
export interface LiteralTypeNode extends TypeNode {
kind: SyntaxKind.LiteralType;
literal: Expression;
@@ -3156,17 +3187,18 @@ namespace ts {
Intersection = 1 << 17, // Intersection (T & U)
Index = 1 << 18, // keyof T
IndexedAccess = 1 << 19, // T[K]
Match = 1 << 20, // T match { U: V }
/* @internal */
FreshLiteral = 1 << 20, // Fresh literal type
FreshLiteral = 1 << 21, // Fresh literal type
/* @internal */
ContainsWideningType = 1 << 21, // Type is or contains undefined or null widening type
ContainsWideningType = 1 << 22, // Type is or contains undefined or null widening type
/* @internal */
ContainsObjectLiteral = 1 << 22, // Type is or contains object literal type
ContainsObjectLiteral = 1 << 23, // Type is or contains object literal type
/* @internal */
ContainsAnyFunctionType = 1 << 23, // Type is or contains the anyFunctionType
NonPrimitive = 1 << 24, // intrinsic object type
ContainsAnyFunctionType = 1 << 24, // Type is or contains the anyFunctionType
NonPrimitive = 1 << 25, // intrinsic object type
/* @internal */
JsxAttributes = 1 << 25, // Jsx attributes type
JsxAttributes = 1 << 26, // Jsx attributes type
/* @internal */
Nullable = Undefined | Null,
@@ -3185,12 +3217,12 @@ namespace ts {
EnumLike = Enum | EnumLiteral,
UnionOrIntersection = Union | Intersection,
StructuredType = Object | Union | Intersection,
StructuredOrTypeVariable = StructuredType | TypeParameter | Index | IndexedAccess,
TypeVariable = TypeParameter | IndexedAccess,
StructuredOrTypeVariable = StructuredType | TypeParameter | Index | IndexedAccess | Match,
TypeVariable = TypeParameter | IndexedAccess | Match,
// 'Narrowable' types are types where narrowing actually narrows.
// This *should* be every type other than null, undefined, void, and never
Narrowable = Any | StructuredType | TypeParameter | Index | IndexedAccess | StringLike | NumberLike | BooleanLike | ESSymbol | NonPrimitive,
Narrowable = Any | StructuredType | TypeParameter | Index | IndexedAccess | Match | StringLike | NumberLike | BooleanLike | ESSymbol | NonPrimitive,
NotUnionOrUnit = Any | ESSymbol | Object | NonPrimitive,
/* @internal */
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
@@ -3420,6 +3452,18 @@ namespace ts {
type: TypeVariable | UnionOrIntersectionType;
}
// T match {} types (TypeFlags.Match)
export interface MatchType extends Type {
typeArgument: Type;
clauses: ReadonlyArray<MatchTypeClause>;
elseType?: Type;
}
export interface MatchTypeClause {
matchType: Type;
resultType: Type;
}
export const enum SignatureKind {
Call,
Construct,
+10 -1
View File
@@ -4844,7 +4844,6 @@ namespace ts {
|| kind === SyntaxKind.BooleanKeyword
|| kind === SyntaxKind.StringKeyword
|| kind === SyntaxKind.SymbolKeyword
|| kind === SyntaxKind.ThisKeyword
|| kind === SyntaxKind.VoidKeyword
|| kind === SyntaxKind.UndefinedKeyword
|| kind === SyntaxKind.NullKeyword
@@ -4871,6 +4870,16 @@ namespace ts {
return false;
}
export function isMatchTypeBlock(node: Node): node is MatchTypeBlock {
return node.kind === SyntaxKind.MatchTypeBlock;
}
export function isMatchTypeMatchOrElseClause(node: Node): node is MatchTypeMatchOrElseClause {
const kind = node.kind;
return kind === SyntaxKind.MatchTypeMatchClause
|| kind === SyntaxKind.MatchTypeElseClause;
}
// Binding patterns
/* @internal */
+18
View File
@@ -405,6 +405,24 @@ namespace ts {
visitNode((<MappedTypeNode>node).questionToken, tokenVisitor, isToken),
visitNode((<MappedTypeNode>node).type, visitor, isTypeNode));
case SyntaxKind.MatchType:
return updateMatchTypeNode(<MatchTypeNode>node,
visitNode((<MatchTypeNode>node).typeArgument, visitor, isTypeNode),
visitNode((<MatchTypeNode>node).matchBlock, visitor, isMatchTypeBlock));
case SyntaxKind.MatchTypeBlock:
return updateMatchTypeBlock(<MatchTypeBlock>node,
nodesVisitor((<MatchTypeBlock>node).clauses, visitor, isMatchTypeMatchOrElseClause));
case SyntaxKind.MatchTypeMatchClause:
return updateMatchTypeMatchClause(<MatchTypeMatchClause>node,
visitNode((<MatchTypeMatchClause>node).matchType, visitor, isTypeNode),
visitNode((<MatchTypeMatchClause>node).resultType, visitor, isTypeNode));
case SyntaxKind.MatchTypeElseClause:
return updateMatchTypeElseClause(<MatchTypeElseClause>node,
visitNode((<MatchTypeElseClause>node).resultType, visitor, isTypeNode));
case SyntaxKind.LiteralType:
return updateLiteralTypeNode(<LiteralTypeNode>node,
visitNode((<LiteralTypeNode>node).literal, visitor, isExpression));