mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-03 18:38:40 -06:00
Add narrowing for non-union types in narrowTypeByDiscriminant
Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com>
This commit is contained in:
parent
ca88611465
commit
90c2555488
@ -29459,6 +29459,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
propType = removeNullable && optionalChain ? getOptionalType(propType) : propType;
|
||||
const narrowedPropType = narrowType(propType);
|
||||
// If the narrowed property type is never and the type is not a union, return never
|
||||
// This handles cases where a non-union type has a single discriminant value that's been exhausted
|
||||
if (narrowedPropType.flags & TypeFlags.Never && !(type.flags & TypeFlags.Union)) {
|
||||
return neverType;
|
||||
}
|
||||
return filterType(type, t => {
|
||||
const discriminantType = getTypeOfPropertyOrIndexSignatureOfType(t, propName) || unknownType;
|
||||
return !(discriminantType.flags & TypeFlags.Never) && !(narrowedPropType.flags & TypeFlags.Never) && areTypesComparable(narrowedPropType, discriminantType);
|
||||
@ -29772,13 +29777,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return caseType;
|
||||
}
|
||||
const defaultType = filterType(type, t => !(isUnitLikeType(t) && contains(switchTypes, t.flags & TypeFlags.Undefined ? undefinedType : getRegularTypeOfLiteralType(extractUnitType(t)), (t1, t2) => isUnitType(t1) && areTypesComparable(t1, t2))));
|
||||
// Allow non-union types to narrow to never in the default case when all values are handled
|
||||
if (!(type.flags & TypeFlags.Union) && isUnitLikeType(type)) {
|
||||
// Allow non-union types to narrow to never when all values are handled
|
||||
// This applies when caseType is never (meaning we're in a default-like position)
|
||||
if (caseType.flags & TypeFlags.Never && !(type.flags & TypeFlags.Union) && isUnitLikeType(type)) {
|
||||
const regularType = type.flags & TypeFlags.Undefined ? undefinedType : getRegularTypeOfLiteralType(extractUnitType(type));
|
||||
if (isUnitType(regularType) && contains(switchTypes, regularType, (t1, t2) => isUnitType(t1) && areTypesComparable(t1, t2))) {
|
||||
return neverType;
|
||||
}
|
||||
}
|
||||
// Also handle single-member unions
|
||||
if (caseType.flags & TypeFlags.Never && type.flags & TypeFlags.Union && (type as UnionType).types.length === 1) {
|
||||
const singleType = (type as UnionType).types[0];
|
||||
if (isUnitLikeType(singleType)) {
|
||||
const regularType = singleType.flags & TypeFlags.Undefined ? undefinedType : getRegularTypeOfLiteralType(extractUnitType(singleType));
|
||||
if (isUnitType(regularType) && contains(switchTypes, regularType, (t1, t2) => isUnitType(t1) && areTypesComparable(t1, t2))) {
|
||||
return neverType;
|
||||
}
|
||||
}
|
||||
}
|
||||
return caseType.flags & TypeFlags.Never ? defaultType : getUnionType([caseType, defaultType]);
|
||||
}
|
||||
|
||||
|
||||
@ -84,7 +84,6 @@ exhaustiveSwitchSingleEnumMember.ts(78,9): error TS2322: Type 'MultiMemberEnum.B
|
||||
!!! error TS2322: Type 'MultiMemberEnum.B' is not assignable to type 'never'.
|
||||
}
|
||||
|
||||
// Note: Discriminated union narrowing for single-member types is a more complex case
|
||||
// that involves property access narrowing, not just direct value narrowing.
|
||||
// This test focuses on direct value narrowing.
|
||||
// Note: Discriminated union narrowing for single-member types requires
|
||||
// narrowing through property access, which is more complex and not yet implemented.
|
||||
|
||||
@ -81,9 +81,8 @@ function testIncomplete(x: MultiMemberEnum) {
|
||||
const n: never = x; // Error expected
|
||||
}
|
||||
|
||||
// Note: Discriminated union narrowing for single-member types is a more complex case
|
||||
// that involves property access narrowing, not just direct value narrowing.
|
||||
// This test focuses on direct value narrowing.
|
||||
// Note: Discriminated union narrowing for single-member types requires
|
||||
// narrowing through property access, which is more complex and not yet implemented.
|
||||
|
||||
|
||||
//// [exhaustiveSwitchSingleEnumMember.js]
|
||||
@ -158,6 +157,5 @@ function testIncomplete(x) {
|
||||
// Should NOT narrow to never - B is not handled
|
||||
var n = x; // Error expected
|
||||
}
|
||||
// Note: Discriminated union narrowing for single-member types is a more complex case
|
||||
// that involves property access narrowing, not just direct value narrowing.
|
||||
// This test focuses on direct value narrowing.
|
||||
// Note: Discriminated union narrowing for single-member types requires
|
||||
// narrowing through property access, which is more complex and not yet implemented.
|
||||
|
||||
@ -167,7 +167,6 @@ function testIncomplete(x: MultiMemberEnum) {
|
||||
>x : Symbol(x, Decl(exhaustiveSwitchSingleEnumMember.ts, 71, 24))
|
||||
}
|
||||
|
||||
// Note: Discriminated union narrowing for single-member types is a more complex case
|
||||
// that involves property access narrowing, not just direct value narrowing.
|
||||
// This test focuses on direct value narrowing.
|
||||
// Note: Discriminated union narrowing for single-member types requires
|
||||
// narrowing through property access, which is more complex and not yet implemented.
|
||||
|
||||
|
||||
@ -249,7 +249,6 @@ function testIncomplete(x: MultiMemberEnum) {
|
||||
> : ^^^^^^^^^^^^^^^^^
|
||||
}
|
||||
|
||||
// Note: Discriminated union narrowing for single-member types is a more complex case
|
||||
// that involves property access narrowing, not just direct value narrowing.
|
||||
// This test focuses on direct value narrowing.
|
||||
// Note: Discriminated union narrowing for single-member types requires
|
||||
// narrowing through property access, which is more complex and not yet implemented.
|
||||
|
||||
|
||||
@ -79,6 +79,5 @@ function testIncomplete(x: MultiMemberEnum) {
|
||||
const n: never = x; // Error expected
|
||||
}
|
||||
|
||||
// Note: Discriminated union narrowing for single-member types is a more complex case
|
||||
// that involves property access narrowing, not just direct value narrowing.
|
||||
// This test focuses on direct value narrowing.
|
||||
// Note: Discriminated union narrowing for single-member types requires
|
||||
// narrowing through property access, which is more complex and not yet implemented.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user