Skip to content

Commit

Permalink
Fixed distributive conditional types with never intersections (#57345)
Browse files Browse the repository at this point in the history
  • Loading branch information
Andarist authored Feb 9, 2024
1 parent c5db0ac commit e2bf8b4
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19877,12 +19877,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (!result) {
const newMapper = createTypeMapper(root.outerTypeParameters, typeArguments);
const checkType = root.checkType;
const distributionType = root.isDistributive ? getMappedType(checkType, newMapper) : undefined;
const distributionType = root.isDistributive ? getReducedType(getMappedType(checkType, newMapper)) : undefined;
// Distributive conditional types are distributed over union types. For example, when the
// distributive conditional type T extends U ? X : Y is instantiated with A | B for T, the
// result is (A extends U ? X : Y) | (B extends U ? X : Y).
result = distributionType && checkType !== distributionType && distributionType.flags & (TypeFlags.Union | TypeFlags.Never) ?
mapTypeWithAlias(getReducedType(distributionType), t => getConditionalType(root, prependTypeMapping(checkType, t, newMapper), forConstraint), aliasSymbol, aliasTypeArguments) :
mapTypeWithAlias(distributionType, t => getConditionalType(root, prependTypeMapping(checkType, t, newMapper), forConstraint), aliasSymbol, aliasTypeArguments) :
getConditionalType(root, newMapper, forConstraint, aliasSymbol, aliasTypeArguments);
root.instantiations!.set(id, result);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//// [tests/cases/compiler/distributiveConditionalTypeNeverIntersection1.ts] ////

=== distributiveConditionalTypeNeverIntersection1.ts ===
// https://github.com/microsoft/TypeScript/issues/57343

type IsNumber<T> = T extends number ? true : false;
>IsNumber : Symbol(IsNumber, Decl(distributiveConditionalTypeNeverIntersection1.ts, 0, 0))
>T : Symbol(T, Decl(distributiveConditionalTypeNeverIntersection1.ts, 2, 14))
>T : Symbol(T, Decl(distributiveConditionalTypeNeverIntersection1.ts, 2, 14))

type Conflicted = { x: true } & { x: false };
>Conflicted : Symbol(Conflicted, Decl(distributiveConditionalTypeNeverIntersection1.ts, 2, 51))
>x : Symbol(x, Decl(distributiveConditionalTypeNeverIntersection1.ts, 4, 19))
>x : Symbol(x, Decl(distributiveConditionalTypeNeverIntersection1.ts, 4, 33))

type Ex1 = IsNumber<Conflicted>; // never
>Ex1 : Symbol(Ex1, Decl(distributiveConditionalTypeNeverIntersection1.ts, 4, 45))
>IsNumber : Symbol(IsNumber, Decl(distributiveConditionalTypeNeverIntersection1.ts, 0, 0))
>Conflicted : Symbol(Conflicted, Decl(distributiveConditionalTypeNeverIntersection1.ts, 2, 51))

type Ex2 = IsNumber<"OEEE" | Conflicted>; // false
>Ex2 : Symbol(Ex2, Decl(distributiveConditionalTypeNeverIntersection1.ts, 6, 32))
>IsNumber : Symbol(IsNumber, Decl(distributiveConditionalTypeNeverIntersection1.ts, 0, 0))
>Conflicted : Symbol(Conflicted, Decl(distributiveConditionalTypeNeverIntersection1.ts, 2, 51))

type Ex3 = IsNumber<1 | Conflicted>; // true
>Ex3 : Symbol(Ex3, Decl(distributiveConditionalTypeNeverIntersection1.ts, 7, 41))
>IsNumber : Symbol(IsNumber, Decl(distributiveConditionalTypeNeverIntersection1.ts, 0, 0))
>Conflicted : Symbol(Conflicted, Decl(distributiveConditionalTypeNeverIntersection1.ts, 2, 51))

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//// [tests/cases/compiler/distributiveConditionalTypeNeverIntersection1.ts] ////

=== distributiveConditionalTypeNeverIntersection1.ts ===
// https://github.com/microsoft/TypeScript/issues/57343

type IsNumber<T> = T extends number ? true : false;
>IsNumber : IsNumber<T>
>true : true
>false : false

type Conflicted = { x: true } & { x: false };
>Conflicted : never
>x : true
>true : true
>x : false
>false : false

type Ex1 = IsNumber<Conflicted>; // never
>Ex1 : never

type Ex2 = IsNumber<"OEEE" | Conflicted>; // false
>Ex2 : false

type Ex3 = IsNumber<1 | Conflicted>; // true
>Ex3 : true

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// @strict: true
// @noEmit: true

// https://github.com/microsoft/TypeScript/issues/57343

type IsNumber<T> = T extends number ? true : false;

type Conflicted = { x: true } & { x: false };

type Ex1 = IsNumber<Conflicted>; // never
type Ex2 = IsNumber<"OEEE" | Conflicted>; // false
type Ex3 = IsNumber<1 | Conflicted>; // true

0 comments on commit e2bf8b4

Please sign in to comment.