Skip to content

Commit ace0904

Browse files
committed
Treat never-like intersections as never
1 parent b8b5948 commit ace0904

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

src/compiler/checker.ts

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10125,7 +10125,7 @@ namespace ts {
1012510125
let checkFlags = 0;
1012610126
for (const current of containingType.types) {
1012710127
const type = getApparentType(current);
10128-
if (type !== errorType) {
10128+
if (type !== errorType && !isNeverLikeType(type)) {
1012910129
const prop = getPropertyOfType(type, name);
1013010130
const modifiers = prop ? getDeclarationModifierFlagsFromSymbol(prop) : 0;
1013110131
if (prop && !(modifiers & excludeModifiers)) {
@@ -10196,6 +10196,9 @@ namespace ts {
1019610196
if (isLiteralType(type)) {
1019710197
checkFlags |= CheckFlags.HasLiteralType;
1019810198
}
10199+
if (type.flags & TypeFlags.Never) {
10200+
checkFlags |= CheckFlags.HasNeverType;
10201+
}
1019910202
propTypes.push(type);
1020010203
}
1020110204
addRange(propTypes, indexTypes);
@@ -10247,6 +10250,22 @@ namespace ts {
1024710250
return property && !(getCheckFlags(property) & CheckFlags.ReadPartial) ? property : undefined;
1024810251
}
1024910252

10253+
function isNeverLikeIntersection(type: IntersectionType) {
10254+
if (!(type.objectFlags & ObjectFlags.IsNeverIntersectionComputed)) {
10255+
type.objectFlags |= ObjectFlags.IsNeverIntersectionComputed |
10256+
(some(getPropertiesOfUnionOrIntersectionType(type), isDiscriminantWithNeverType) ? ObjectFlags.IsNeverIntersection : 0);
10257+
}
10258+
return !!(type.objectFlags & ObjectFlags.IsNeverIntersection);
10259+
}
10260+
10261+
function isDiscriminantWithNeverType(prop: Symbol) {
10262+
return (getCheckFlags(prop) & (CheckFlags.Discriminant | CheckFlags.HasNeverType)) === CheckFlags.Discriminant && !!(getTypeOfSymbol(prop).flags & TypeFlags.Never);
10263+
}
10264+
10265+
function isNeverLikeType(type: Type) {
10266+
return !!(type.flags & TypeFlags.Never || type.flags & TypeFlags.Intersection && isNeverLikeIntersection(<IntersectionType>type));
10267+
}
10268+
1025010269
/**
1025110270
* Return the symbol for the property with the given name in the given type. Creates synthetic union properties when
1025210271
* necessary, maps primitive types and type parameters are to their apparent types, and augments with properties from
@@ -10275,7 +10294,7 @@ namespace ts {
1027510294
}
1027610295
return getPropertyOfObjectType(globalObjectType, name);
1027710296
}
10278-
if (type.flags & TypeFlags.UnionOrIntersection) {
10297+
if (type.flags & TypeFlags.Union || type.flags & TypeFlags.Intersection && !isNeverLikeIntersection(<IntersectionType>type)) {
1027910298
return getPropertyOfUnionOrIntersectionType(<UnionOrIntersectionType>type, name);
1028010299
}
1028110300
return undefined;
@@ -12383,9 +12402,12 @@ namespace ts {
1238312402
}
1238412403
}
1238512404
if (!(indexType.flags & TypeFlags.Nullable) && isTypeAssignableToKind(indexType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbolLike)) {
12386-
if (objectType.flags & (TypeFlags.Any | TypeFlags.Never)) {
12405+
if (objectType.flags & TypeFlags.Any) {
1238712406
return objectType;
1238812407
}
12408+
if (isNeverLikeType(objectType)) {
12409+
return neverType;
12410+
}
1238912411
const stringIndexInfo = getIndexInfoOfType(objectType, IndexKind.String);
1239012412
const indexInfo = isTypeAssignableToKind(indexType, TypeFlags.NumberLike) && getIndexInfoOfType(objectType, IndexKind.Number) || stringIndexInfo;
1239112413
if (indexInfo) {
@@ -15181,6 +15203,9 @@ namespace ts {
1518115203
result = typeRelatedToSomeType(getRegularTypeOfObjectLiteral(source), <UnionType>target, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive));
1518215204
}
1518315205
else if (target.flags & TypeFlags.Intersection) {
15206+
if (isNeverLikeIntersection(<IntersectionType>target)) {
15207+
return Ternary.False;
15208+
}
1518415209
result = typeRelatedToEachType(getRegularTypeOfObjectLiteral(source), target as IntersectionType, reportErrors, IntersectionState.Target);
1518515210
if (result && (isPerformingExcessPropertyChecks || isPerformingCommonPropertyChecks)) {
1518615211
// Validate against excess props using the original `source`
@@ -15190,6 +15215,9 @@ namespace ts {
1519015215
}
1519115216
}
1519215217
else if (source.flags & TypeFlags.Intersection) {
15218+
if (isNeverLikeIntersection(<IntersectionType>source)) {
15219+
return Ternary.True;
15220+
}
1519315221
// Check to see if any constituents of the intersection are immediately related to the target.
1519415222
//
1519515223
// Don't report errors though. Checking whether a constituent is related to the source is not actually

src/compiler/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4131,6 +4131,7 @@ namespace ts {
41314131
OptionalParameter = 1 << 14, // Optional parameter
41324132
RestParameter = 1 << 15, // Rest parameter
41334133
DeferredType = 1 << 16, // Calculation of the type of this symbol is deferred due to processing costs, should be fetched with `getTypeOfSymbolWithDeferredType`
4134+
HasNeverType = 1 << 17, // Synthetic property with at least one never type in constituents
41344135
Synthetic = SyntheticProperty | SyntheticMethod,
41354136
Discriminant = HasNonUniformType | HasLiteralType,
41364137
Partial = ReadPartial | WritePartial
@@ -4459,6 +4460,10 @@ namespace ts {
44594460
IsGenericIndexTypeComputed = 1 << 24, // IsGenericIndexType flag has been computed
44604461
/* @internal */
44614462
IsGenericIndexType = 1 << 25, // Union or intersection contains generic index type
4463+
/* @internal */
4464+
IsNeverIntersectionComputed = 1 << 26,
4465+
/* @internal */
4466+
IsNeverIntersection = 1 << 27,
44624467
ClassOrInterface = Class | Interface,
44634468
/* @internal */
44644469
RequiresWidening = ContainsWideningType | ContainsObjectOrArrayLiteral,

0 commit comments

Comments
 (0)