@@ -121,9 +121,9 @@ namespace ts {
121
121
const nullType = createIntrinsicType(TypeFlags.Null | nullableWideningFlags, "null");
122
122
const emptyArrayElementType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefinedOrNull, "undefined");
123
123
const unknownType = createIntrinsicType(TypeFlags.Any, "unknown");
124
+ const neverType = createIntrinsicType(TypeFlags.Never, "never");
124
125
125
126
const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
126
- const nothingType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
127
127
const emptyGenericType = <GenericType><ObjectType>createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
128
128
emptyGenericType.instantiations = {};
129
129
@@ -2030,12 +2030,7 @@ namespace ts {
2030
2030
writeUnionOrIntersectionType(<UnionOrIntersectionType>type, flags);
2031
2031
}
2032
2032
else if (type.flags & TypeFlags.Anonymous) {
2033
- if (type === nothingType) {
2034
- writer.writeKeyword("nothing");
2035
- }
2036
- else {
2037
- writeAnonymousType(<ObjectType>type, flags);
2038
- }
2033
+ writeAnonymousType(<ObjectType>type, flags);
2039
2034
}
2040
2035
else if (type.flags & TypeFlags.StringLiteral) {
2041
2036
writer.writeStringLiteral(`"${escapeString((<StringLiteralType>type).text)}"`);
@@ -3676,6 +3671,7 @@ namespace ts {
3676
3671
case SyntaxKind.VoidKeyword:
3677
3672
case SyntaxKind.UndefinedKeyword:
3678
3673
case SyntaxKind.NullKeyword:
3674
+ case SyntaxKind.NeverKeyword:
3679
3675
case SyntaxKind.StringLiteralType:
3680
3676
return true;
3681
3677
case SyntaxKind.ArrayType:
@@ -5011,7 +5007,7 @@ namespace ts {
5011
5007
if (type.flags & TypeFlags.Undefined) typeSet.containsUndefined = true;
5012
5008
if (type.flags & TypeFlags.Null) typeSet.containsNull = true;
5013
5009
}
5014
- else if (type !== nothingType && !contains(typeSet, type)) {
5010
+ else if (type !== neverType && !contains(typeSet, type)) {
5015
5011
typeSet.push(type);
5016
5012
}
5017
5013
}
@@ -5052,7 +5048,7 @@ namespace ts {
5052
5048
// a named type that circularly references itself.
5053
5049
function getUnionType(types: Type[], noSubtypeReduction?: boolean): Type {
5054
5050
if (types.length === 0) {
5055
- return nothingType ;
5051
+ return neverType ;
5056
5052
}
5057
5053
if (types.length === 1) {
5058
5054
return types[0];
@@ -5072,7 +5068,7 @@ namespace ts {
5072
5068
if (typeSet.length === 0) {
5073
5069
return typeSet.containsNull ? nullType :
5074
5070
typeSet.containsUndefined ? undefinedType :
5075
- nothingType ;
5071
+ neverType ;
5076
5072
}
5077
5073
else if (typeSet.length === 1) {
5078
5074
return typeSet[0];
@@ -5220,6 +5216,8 @@ namespace ts {
5220
5216
return undefinedType;
5221
5217
case SyntaxKind.NullKeyword:
5222
5218
return nullType;
5219
+ case SyntaxKind.NeverKeyword:
5220
+ return neverType;
5223
5221
case SyntaxKind.ThisType:
5224
5222
case SyntaxKind.ThisKeyword:
5225
5223
return getTypeFromThisTypeNode(node);
@@ -5865,28 +5863,28 @@ namespace ts {
5865
5863
return isIdenticalTo(source, target);
5866
5864
}
5867
5865
5868
- if (target.flags & TypeFlags.Any) return Ternary.True;
5869
- if (source.flags & TypeFlags.Undefined) {
5870
- if (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void) || source === emptyArrayElementType) return Ternary.True;
5871
- }
5872
- if (source.flags & TypeFlags.Null) {
5873
- if (!strictNullChecks || target.flags & TypeFlags.Null) return Ternary.True;
5874
- }
5875
- if (source.flags & TypeFlags.Enum && target === numberType) return Ternary.True;
5876
- if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) {
5877
- if (result = enumRelatedTo(source, target, reportErrors)) {
5878
- return result;
5866
+ if (!(target.flags & TypeFlags.Never)) {
5867
+ if (target.flags & TypeFlags.Any) return Ternary.True;
5868
+ if (source.flags & TypeFlags.Undefined) {
5869
+ if (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void) || source === emptyArrayElementType) return Ternary.True;
5870
+ }
5871
+ if (source.flags & TypeFlags.Null) {
5872
+ if (!strictNullChecks || target.flags & TypeFlags.Null) return Ternary.True;
5873
+ }
5874
+ if (source.flags & TypeFlags.Enum && target === numberType) return Ternary.True;
5875
+ if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) {
5876
+ if (result = enumRelatedTo(source, target, reportErrors)) {
5877
+ return result;
5878
+ }
5879
+ }
5880
+ if (source.flags & TypeFlags.StringLiteral && target === stringType) return Ternary.True;
5881
+ if (relation === assignableRelation || relation === comparableRelation) {
5882
+ if (source.flags & (TypeFlags.Any | TypeFlags.Never)) return Ternary.True;
5883
+ if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True;
5884
+ }
5885
+ if (source.flags & TypeFlags.Boolean && target.flags & TypeFlags.Boolean) {
5886
+ return Ternary.True;
5879
5887
}
5880
- }
5881
- if (source.flags & TypeFlags.StringLiteral && target === stringType) return Ternary.True;
5882
-
5883
- if (relation === assignableRelation || relation === comparableRelation) {
5884
- if (isTypeAny(source)) return Ternary.True;
5885
- if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True;
5886
- }
5887
-
5888
- if (source.flags & TypeFlags.Boolean && target.flags & TypeFlags.Boolean) {
5889
- return Ternary.True;
5890
5888
}
5891
5889
5892
5890
if (source.flags & TypeFlags.FreshObjectLiteral) {
@@ -7491,7 +7489,7 @@ namespace ts {
7491
7489
7492
7490
function getTypeWithFacts(type: Type, include: TypeFacts) {
7493
7491
if (!(type.flags & TypeFlags.Union)) {
7494
- return getTypeFacts(type) & include ? type : nothingType ;
7492
+ return getTypeFacts(type) & include ? type : neverType ;
7495
7493
}
7496
7494
let firstType: Type;
7497
7495
let types: Type[];
@@ -7508,7 +7506,7 @@ namespace ts {
7508
7506
}
7509
7507
}
7510
7508
}
7511
- return firstType ? types ? getUnionType(types, /*noSubtypeReduction*/ true) : firstType : nothingType ;
7509
+ return firstType ? types ? getUnionType(types, /*noSubtypeReduction*/ true) : firstType : neverType ;
7512
7510
}
7513
7511
7514
7512
function getTypeWithDefault(type: Type, defaultExpression: Expression) {
@@ -7629,7 +7627,7 @@ namespace ts {
7629
7627
const visitedFlowStart = visitedFlowCount;
7630
7628
const result = getTypeAtFlowNode(reference.flowNode);
7631
7629
visitedFlowCount = visitedFlowStart;
7632
- if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(result, TypeFacts.NEUndefinedOrNull) === nothingType ) {
7630
+ if (reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(result, TypeFacts.NEUndefinedOrNull) === neverType ) {
7633
7631
return declaredType;
7634
7632
}
7635
7633
return result;
@@ -7717,7 +7715,7 @@ namespace ts {
7717
7715
7718
7716
function getTypeAtFlowCondition(flow: FlowCondition) {
7719
7717
let type = getTypeAtFlowNode(flow.antecedent);
7720
- if (type !== nothingType ) {
7718
+ if (type !== neverType ) {
7721
7719
// If we have an antecedent type (meaning we're reachable in some way), we first
7722
7720
// attempt to narrow the antecedent type. If that produces the nothing type, then
7723
7721
// we take the type guard as an indication that control could reach here in a
@@ -7727,7 +7725,7 @@ namespace ts {
7727
7725
// narrow that.
7728
7726
const assumeTrue = (flow.flags & FlowFlags.TrueCondition) !== 0;
7729
7727
type = narrowType(type, flow.expression, assumeTrue);
7730
- if (type === nothingType ) {
7728
+ if (type === neverType ) {
7731
7729
type = narrowType(declaredType, flow.expression, assumeTrue);
7732
7730
}
7733
7731
}
@@ -7949,7 +7947,7 @@ namespace ts {
7949
7947
const targetType = type.flags & TypeFlags.TypeParameter ? getApparentType(type) : type;
7950
7948
return isTypeAssignableTo(candidate, targetType) ? candidate :
7951
7949
isTypeAssignableTo(type, candidate) ? type :
7952
- nothingType ;
7950
+ neverType ;
7953
7951
}
7954
7952
7955
7953
function narrowTypeByTypePredicate(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type {
@@ -11561,6 +11559,9 @@ namespace ts {
11561
11559
else {
11562
11560
const hasImplicitReturn = !!(func.flags & NodeFlags.HasImplicitReturn);
11563
11561
types = checkAndAggregateReturnExpressionTypes(<Block>func.body, contextualMapper, isAsync, hasImplicitReturn);
11562
+ if (!types) {
11563
+ return neverType;
11564
+ }
11564
11565
if (types.length === 0) {
11565
11566
if (isAsync) {
11566
11567
// For an async function, the return type will not be void, but rather a Promise for void.
@@ -11569,12 +11570,9 @@ namespace ts {
11569
11570
error(func, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
11570
11571
return unknownType;
11571
11572
}
11572
-
11573
11573
return promiseType;
11574
11574
}
11575
- else {
11576
- return voidType;
11577
- }
11575
+ return voidType;
11578
11576
}
11579
11577
}
11580
11578
// When yield/return statements are contextually typed we allow the return type to be a union type.
@@ -11654,14 +11652,17 @@ namespace ts {
11654
11652
// the native Promise<T> type by the caller.
11655
11653
type = checkAwaitedType(type, body.parent, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member);
11656
11654
}
11657
- if (!contains(aggregatedTypes, type)) {
11655
+ if (type !== neverType && !contains(aggregatedTypes, type)) {
11658
11656
aggregatedTypes.push(type);
11659
11657
}
11660
11658
}
11661
11659
else {
11662
11660
hasOmittedExpressions = true;
11663
11661
}
11664
11662
});
11663
+ if (aggregatedTypes.length === 0 && !hasOmittedExpressions && !hasImplicitReturn) {
11664
+ return undefined;
11665
+ }
11665
11666
if (strictNullChecks && aggregatedTypes.length && (hasOmittedExpressions || hasImplicitReturn)) {
11666
11667
if (!contains(aggregatedTypes, undefinedType)) {
11667
11668
aggregatedTypes.push(undefinedType);
@@ -11697,7 +11698,10 @@ namespace ts {
11697
11698
11698
11699
const hasExplicitReturn = func.flags & NodeFlags.HasExplicitReturn;
11699
11700
11700
- if (returnType && !hasExplicitReturn) {
11701
+ if (returnType === neverType) {
11702
+ error(func.type, Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point);
11703
+ }
11704
+ else if (returnType && !hasExplicitReturn) {
11701
11705
// minimal check: function has syntactic return type annotation and no explicit return statements in the body
11702
11706
// this function does not conform to the specification.
11703
11707
// NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present
@@ -14761,7 +14765,7 @@ namespace ts {
14761
14765
arrayType = getUnionType(filter((arrayOrStringType as UnionType).types, t => !(t.flags & TypeFlags.StringLike)));
14762
14766
}
14763
14767
else if (arrayOrStringType.flags & TypeFlags.StringLike) {
14764
- arrayType = nothingType ;
14768
+ arrayType = neverType ;
14765
14769
}
14766
14770
const hasStringConstituent = arrayOrStringType !== arrayType;
14767
14771
let reportedError = false;
@@ -14773,7 +14777,7 @@ namespace ts {
14773
14777
14774
14778
// Now that we've removed all the StringLike types, if no constituents remain, then the entire
14775
14779
// arrayOrStringType was a string.
14776
- if (arrayType === nothingType ) {
14780
+ if (arrayType === neverType ) {
14777
14781
return stringType;
14778
14782
}
14779
14783
}
@@ -14834,7 +14838,7 @@ namespace ts {
14834
14838
if (func) {
14835
14839
const signature = getSignatureFromDeclaration(func);
14836
14840
const returnType = getReturnTypeOfSignature(signature);
14837
- if (strictNullChecks || node.expression) {
14841
+ if (strictNullChecks || node.expression || returnType === neverType ) {
14838
14842
const exprType = node.expression ? checkExpressionCached(node.expression) : undefinedType;
14839
14843
14840
14844
if (func.asteriskToken) {
0 commit comments