Skip to content

Commit 1befac3

Browse files
committed
feat: introduce throw type
1 parent 6f0c91c commit 1befac3

File tree

5 files changed

+38
-4
lines changed

5 files changed

+38
-4
lines changed

src/compiler/checker.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4524,6 +4524,9 @@ namespace ts {
45244524
if (type.flags & TypeFlags.Substitution) {
45254525
return typeToTypeNodeHelper((<SubstitutionType>type).baseType, context);
45264526
}
4527+
if (type.flags & TypeFlags.ThrowType) {
4528+
return typeToTypeNodeHelper(errorType, context);
4529+
}
45274530

45284531
return Debug.fail("Should be unreachable.");
45294532

@@ -13434,6 +13437,9 @@ namespace ts {
1343413437
case SyntaxKind.ReadonlyKeyword:
1343513438
links.resolvedType = getTypeFromTypeNode(node.type);
1343613439
break;
13440+
case SyntaxKind.ThrowKeyword:
13441+
links.resolvedType = createThrowType(getTypeFromTypeNode(node.type));
13442+
break;
1343713443
default:
1343813444
throw Debug.assertNever(node.operator);
1343913445
}
@@ -14504,6 +14510,12 @@ namespace ts {
1450414510
return type;
1450514511
}
1450614512

14513+
function createThrowType(containingType: Type) {
14514+
const type = <ThrowType>createType(TypeFlags.ThrowType);
14515+
type.value = containingType;
14516+
return type;
14517+
}
14518+
1450714519
function getESSymbolLikeTypeForNode(node: Node) {
1450814520
if (isValidESSymbolDeclaration(node)) {
1450914521
const symbol = getSymbolOfNode(node);
@@ -15156,6 +15168,15 @@ namespace ts {
1515615168
return sub;
1515715169
}
1515815170
}
15171+
if (flags & TypeFlags.ThrowType) {
15172+
const innerType = instantiateType((<ThrowType>type).value, mapper);
15173+
let errorMessage = "Unknown";
15174+
if (innerType.flags & TypeFlags.StringLiteral) {
15175+
errorMessage = (<StringLiteralType>innerType).value;
15176+
}
15177+
error(currentNode, Diagnostics.Type_instantiated_results_in_a_throw_type_saying_Colon_0, errorMessage);
15178+
return errorType;
15179+
}
1515915180
return type;
1516015181
}
1516115182

@@ -19366,6 +19387,9 @@ namespace ts {
1936619387
// results for union and intersection types for performance reasons.
1936719388
function couldContainTypeVariables(type: Type): boolean {
1936819389
const objectFlags = getObjectFlags(type);
19390+
if (type.flags & TypeFlags.ThrowType) {
19391+
return couldContainTypeVariables((<ThrowType>type).value);
19392+
}
1936919393
if (objectFlags & ObjectFlags.CouldContainTypeVariablesComputed) {
1937019394
return !!(objectFlags & ObjectFlags.CouldContainTypeVariables);
1937119395
}

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3032,6 +3032,10 @@
30323032
"category": "Error",
30333033
"code": 2793
30343034
},
3035+
"Type instantiated results in a throw type saying: {0}": {
3036+
"category": "Error",
3037+
"code": 2794
3038+
},
30353039

30363040
"Import declaration '{0}' is using private name '{1}'.": {
30373041
"category": "Error",

src/compiler/factory/nodeFactory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1975,7 +1975,7 @@ namespace ts {
19751975
}
19761976

19771977
// @api
1978-
function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode {
1978+
function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.ThrowKeyword, type: TypeNode): TypeOperatorNode {
19791979
const node = createBaseNode<TypeOperatorNode>(SyntaxKind.TypeOperator);
19801980
node.operator = operator;
19811981
node.type = parenthesizerRules().parenthesizeMemberOfElementType(type);

src/compiler/parser.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3593,7 +3593,7 @@ namespace ts {
35933593
return type;
35943594
}
35953595

3596-
function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword) {
3596+
function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.ThrowKeyword) {
35973597
const pos = getNodePos();
35983598
parseExpected(operator);
35993599
return finishNode(factory.createTypeOperatorNode(operator, parseTypeOperatorOrHigher()), pos);
@@ -3623,6 +3623,7 @@ namespace ts {
36233623
case SyntaxKind.KeyOfKeyword:
36243624
case SyntaxKind.UniqueKeyword:
36253625
case SyntaxKind.ReadonlyKeyword:
3626+
case SyntaxKind.ThrowKeyword:
36263627
return parseTypeOperator(operator);
36273628
case SyntaxKind.InferKeyword:
36283629
return parseInferType();

src/compiler/types.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,7 +1615,7 @@ namespace ts {
16151615

16161616
export interface TypeOperatorNode extends TypeNode {
16171617
readonly kind: SyntaxKind.TypeOperator;
1618-
readonly operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword;
1618+
readonly operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.ThrowKeyword;
16191619
readonly type: TypeNode;
16201620
}
16211621

@@ -4885,6 +4885,7 @@ namespace ts {
48854885
Substitution = 1 << 25, // Type parameter substitution
48864886
NonPrimitive = 1 << 26, // intrinsic object type
48874887
TemplateLiteral = 1 << 27, // Template literal type
4888+
ThrowType = 1 << 28, // throw T
48884889

48894890
/* @internal */
48904891
AnyOrUnknown = Any | Unknown,
@@ -5020,6 +5021,10 @@ namespace ts {
50205021
export interface EnumType extends Type {
50215022
}
50225023

5024+
export interface ThrowType extends Type {
5025+
value: Type;
5026+
}
5027+
50235028
export const enum ObjectFlags {
50245029
Class = 1 << 0, // Class
50255030
Interface = 1 << 1, // Interface
@@ -6801,7 +6806,7 @@ namespace ts {
68016806
createParenthesizedType(type: TypeNode): ParenthesizedTypeNode;
68026807
updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode): ParenthesizedTypeNode;
68036808
createThisTypeNode(): ThisTypeNode;
6804-
createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode;
6809+
createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.ThrowKeyword, type: TypeNode): TypeOperatorNode;
68056810
updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode): TypeOperatorNode;
68066811
createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode;
68076812
updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode): IndexedAccessTypeNode;

0 commit comments

Comments
 (0)