Skip to content

Commit c11d691

Browse files
committed
Introduce 'never' type
1 parent dc900de commit c11d691

File tree

6 files changed

+24
-15
lines changed

6 files changed

+24
-15
lines changed

src/compiler/checker.ts

+18-15
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ namespace ts {
122122
const unknownType = createIntrinsicType(TypeFlags.Any, "unknown");
123123

124124
const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
125-
const nothingType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
125+
const neverType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
126126
const emptyGenericType = <GenericType><ObjectType>createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
127127
emptyGenericType.instantiations = {};
128128

@@ -2029,8 +2029,8 @@ namespace ts {
20292029
writeUnionOrIntersectionType(<UnionOrIntersectionType>type, flags);
20302030
}
20312031
else if (type.flags & TypeFlags.Anonymous) {
2032-
if (type === nothingType) {
2033-
writer.writeKeyword("nothing");
2032+
if (type === neverType) {
2033+
writer.writeKeyword("never");
20342034
}
20352035
else {
20362036
writeAnonymousType(<ObjectType>type, flags);
@@ -3670,6 +3670,7 @@ namespace ts {
36703670
case SyntaxKind.VoidKeyword:
36713671
case SyntaxKind.UndefinedKeyword:
36723672
case SyntaxKind.NullKeyword:
3673+
case SyntaxKind.NeverKeyword:
36733674
case SyntaxKind.StringLiteralType:
36743675
return true;
36753676
case SyntaxKind.ArrayType:
@@ -5005,7 +5006,7 @@ namespace ts {
50055006
if (type.flags & TypeFlags.Undefined) typeSet.containsUndefined = true;
50065007
if (type.flags & TypeFlags.Null) typeSet.containsNull = true;
50075008
}
5008-
else if (type !== nothingType && !contains(typeSet, type)) {
5009+
else if (type !== neverType && !contains(typeSet, type)) {
50095010
typeSet.push(type);
50105011
}
50115012
}
@@ -5046,7 +5047,7 @@ namespace ts {
50465047
// a named type that circularly references itself.
50475048
function getUnionType(types: Type[], noSubtypeReduction?: boolean): Type {
50485049
if (types.length === 0) {
5049-
return nothingType;
5050+
return neverType;
50505051
}
50515052
if (types.length === 1) {
50525053
return types[0];
@@ -5066,7 +5067,7 @@ namespace ts {
50665067
if (typeSet.length === 0) {
50675068
return typeSet.containsNull ? nullType :
50685069
typeSet.containsUndefined ? undefinedType :
5069-
nothingType;
5070+
neverType;
50705071
}
50715072
else if (typeSet.length === 1) {
50725073
return typeSet[0];
@@ -5214,6 +5215,8 @@ namespace ts {
52145215
return undefinedType;
52155216
case SyntaxKind.NullKeyword:
52165217
return nullType;
5218+
case SyntaxKind.NeverKeyword:
5219+
return neverType;
52175220
case SyntaxKind.ThisType:
52185221
case SyntaxKind.ThisKeyword:
52195222
return getTypeFromThisTypeNode(node);
@@ -7485,7 +7488,7 @@ namespace ts {
74857488

74867489
function getTypeWithFacts(type: Type, include: TypeFacts) {
74877490
if (!(type.flags & TypeFlags.Union)) {
7488-
return getTypeFacts(type) & include ? type : nothingType;
7491+
return getTypeFacts(type) & include ? type : neverType;
74897492
}
74907493
let firstType: Type;
74917494
let types: Type[];
@@ -7502,7 +7505,7 @@ namespace ts {
75027505
}
75037506
}
75047507
}
7505-
return firstType ? types ? getUnionType(types, /*noSubtypeReduction*/ true) : firstType : nothingType;
7508+
return firstType ? types ? getUnionType(types, /*noSubtypeReduction*/ true) : firstType : neverType;
75067509
}
75077510

75087511
function getTypeWithDefault(type: Type, defaultExpression: Expression) {
@@ -7622,7 +7625,7 @@ namespace ts {
76227625
const visitedFlowStart = visitedFlowCount;
76237626
const result = getTypeAtFlowNode(reference.flowNode);
76247627
visitedFlowCount = visitedFlowStart;
7625-
if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(result, TypeFacts.NEUndefinedOrNull) === nothingType) {
7628+
if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(result, TypeFacts.NEUndefinedOrNull) === neverType) {
76267629
return declaredType;
76277630
}
76287631
return result;
@@ -7710,7 +7713,7 @@ namespace ts {
77107713

77117714
function getTypeAtFlowCondition(flow: FlowCondition) {
77127715
let type = getTypeAtFlowNode(flow.antecedent);
7713-
if (type !== nothingType) {
7716+
if (type !== neverType) {
77147717
// If we have an antecedent type (meaning we're reachable in some way), we first
77157718
// attempt to narrow the antecedent type. If that produces the nothing type, then
77167719
// we take the type guard as an indication that control could reach here in a
@@ -7720,7 +7723,7 @@ namespace ts {
77207723
// narrow that.
77217724
const assumeTrue = (flow.flags & FlowFlags.TrueCondition) !== 0;
77227725
type = narrowType(type, flow.expression, assumeTrue);
7723-
if (type === nothingType) {
7726+
if (type === neverType) {
77247727
type = narrowType(declaredType, flow.expression, assumeTrue);
77257728
}
77267729
}
@@ -7942,7 +7945,7 @@ namespace ts {
79427945
const targetType = type.flags & TypeFlags.TypeParameter ? getApparentType(type) : type;
79437946
return isTypeAssignableTo(candidate, targetType) ? candidate :
79447947
isTypeAssignableTo(type, candidate) ? type :
7945-
nothingType;
7948+
neverType;
79467949
}
79477950

79487951
function narrowTypeByTypePredicate(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type {
@@ -11559,7 +11562,7 @@ namespace ts {
1155911562
return promiseType;
1156011563
}
1156111564
else {
11562-
return voidType;
11565+
return hasImplicitReturn ? voidType : neverType;
1156311566
}
1156411567
}
1156511568
}
@@ -14747,7 +14750,7 @@ namespace ts {
1474714750
arrayType = getUnionType(filter((arrayOrStringType as UnionType).types, t => !(t.flags & TypeFlags.StringLike)));
1474814751
}
1474914752
else if (arrayOrStringType.flags & TypeFlags.StringLike) {
14750-
arrayType = nothingType;
14753+
arrayType = neverType;
1475114754
}
1475214755
const hasStringConstituent = arrayOrStringType !== arrayType;
1475314756
let reportedError = false;
@@ -14759,7 +14762,7 @@ namespace ts {
1475914762

1476014763
// Now that we've removed all the StringLike types, if no constituents remain, then the entire
1476114764
// arrayOrStringType was a string.
14762-
if (arrayType === nothingType) {
14765+
if (arrayType === neverType) {
1476314766
return stringType;
1476414767
}
1476514768
}

src/compiler/declarationEmitter.ts

+1
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ namespace ts {
395395
case SyntaxKind.VoidKeyword:
396396
case SyntaxKind.UndefinedKeyword:
397397
case SyntaxKind.NullKeyword:
398+
case SyntaxKind.NeverKeyword:
398399
case SyntaxKind.ThisType:
399400
case SyntaxKind.StringLiteralType:
400401
return writeTextOfNode(currentText, type);

src/compiler/parser.ts

+2
Original file line numberDiff line numberDiff line change
@@ -2368,6 +2368,7 @@ namespace ts {
23682368
case SyntaxKind.BooleanKeyword:
23692369
case SyntaxKind.SymbolKeyword:
23702370
case SyntaxKind.UndefinedKeyword:
2371+
case SyntaxKind.NeverKeyword:
23712372
// If these are followed by a dot, then parse these out as a dotted type reference instead.
23722373
const node = tryParse(parseKeywordAndNoDot);
23732374
return node || parseTypeReference();
@@ -2410,6 +2411,7 @@ namespace ts {
24102411
case SyntaxKind.NullKeyword:
24112412
case SyntaxKind.ThisKeyword:
24122413
case SyntaxKind.TypeOfKeyword:
2414+
case SyntaxKind.NeverKeyword:
24132415
case SyntaxKind.OpenBraceToken:
24142416
case SyntaxKind.OpenBracketToken:
24152417
case SyntaxKind.LessThanToken:

src/compiler/scanner.ts

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ namespace ts {
9191
"let": SyntaxKind.LetKeyword,
9292
"module": SyntaxKind.ModuleKeyword,
9393
"namespace": SyntaxKind.NamespaceKeyword,
94+
"never": SyntaxKind.NeverKeyword,
9495
"new": SyntaxKind.NewKeyword,
9596
"null": SyntaxKind.NullKeyword,
9697
"number": SyntaxKind.NumberKeyword,

src/compiler/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ namespace ts {
164164
IsKeyword,
165165
ModuleKeyword,
166166
NamespaceKeyword,
167+
NeverKeyword,
167168
ReadonlyKeyword,
168169
RequireKeyword,
169170
NumberKeyword,

src/compiler/utilities.ts

+1
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,7 @@ namespace ts {
613613
case SyntaxKind.BooleanKeyword:
614614
case SyntaxKind.SymbolKeyword:
615615
case SyntaxKind.UndefinedKeyword:
616+
case SyntaxKind.NeverKeyword:
616617
return true;
617618
case SyntaxKind.VoidKeyword:
618619
return node.parent.kind !== SyntaxKind.VoidExpression;

0 commit comments

Comments
 (0)