mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-27 06:03:48 -06:00
Fix isUnitLikeType to (again) handle tagged literal types (#51545)
* Fix isUnitLikeType to (again) handle tagged literal types * Add regression test
This commit is contained in:
parent
16edc29bc9
commit
8036b149a4
@ -22633,7 +22633,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
function isUnitLikeType(type: Type): boolean {
|
||||
return isUnitType(getBaseConstraintOrType(type));
|
||||
// Intersections that reduce to 'never' (e.g. 'T & null' where 'T extends {}') are not unit types.
|
||||
const t = getBaseConstraintOrType(type);
|
||||
// Scan intersections such that tagged literal types are considered unit types.
|
||||
return t.flags & TypeFlags.Intersection ? some((t as IntersectionType).types, isUnitType) : isUnitType(t);
|
||||
}
|
||||
|
||||
function extractUnitType(type: Type) {
|
||||
|
||||
@ -444,4 +444,26 @@ tests/cases/conformance/types/unknown/unknownControlFlow.ts(293,5): error TS2345
|
||||
function x<T_AB extends AB>(x: T_AB & undefined, y: any) {
|
||||
let r2: never = y as T_AB & undefined;
|
||||
}
|
||||
|
||||
// Repro from #51538
|
||||
|
||||
type Left = 'left';
|
||||
type Right = 'right' & { right: 'right' };
|
||||
type Either = Left | Right;
|
||||
|
||||
function assertNever(v: never): never {
|
||||
throw new Error('never');
|
||||
}
|
||||
|
||||
function fx20(value: Either) {
|
||||
if (value === 'left') {
|
||||
const foo: 'left' = value;
|
||||
}
|
||||
else if (value === 'right') {
|
||||
const bar: 'right' = value;
|
||||
}
|
||||
else {
|
||||
assertNever(value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -427,6 +427,28 @@ type AB = "A" | "B";
|
||||
function x<T_AB extends AB>(x: T_AB & undefined, y: any) {
|
||||
let r2: never = y as T_AB & undefined;
|
||||
}
|
||||
|
||||
// Repro from #51538
|
||||
|
||||
type Left = 'left';
|
||||
type Right = 'right' & { right: 'right' };
|
||||
type Either = Left | Right;
|
||||
|
||||
function assertNever(v: never): never {
|
||||
throw new Error('never');
|
||||
}
|
||||
|
||||
function fx20(value: Either) {
|
||||
if (value === 'left') {
|
||||
const foo: 'left' = value;
|
||||
}
|
||||
else if (value === 'right') {
|
||||
const bar: 'right' = value;
|
||||
}
|
||||
else {
|
||||
assertNever(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [unknownControlFlow.js]
|
||||
@ -772,6 +794,20 @@ function doSomething2(value) {
|
||||
function x(x, y) {
|
||||
var r2 = y;
|
||||
}
|
||||
function assertNever(v) {
|
||||
throw new Error('never');
|
||||
}
|
||||
function fx20(value) {
|
||||
if (value === 'left') {
|
||||
var foo_1 = value;
|
||||
}
|
||||
else if (value === 'right') {
|
||||
var bar = value;
|
||||
}
|
||||
else {
|
||||
assertNever(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [unknownControlFlow.d.ts]
|
||||
@ -844,3 +880,10 @@ type R<T extends keyof TypeA> = T extends keyof TypeB ? [TypeA[T], TypeB[T]] : n
|
||||
type R2<T extends PropertyKey> = T extends keyof TypeA ? T extends keyof TypeB ? [TypeA[T], TypeB[T]] : never : never;
|
||||
type AB = "A" | "B";
|
||||
declare function x<T_AB extends AB>(x: T_AB & undefined, y: any): void;
|
||||
type Left = 'left';
|
||||
type Right = 'right' & {
|
||||
right: 'right';
|
||||
};
|
||||
type Either = Left | Right;
|
||||
declare function assertNever(v: never): never;
|
||||
declare function fx20(value: Either): void;
|
||||
|
||||
@ -995,3 +995,51 @@ function x<T_AB extends AB>(x: T_AB & undefined, y: any) {
|
||||
>T_AB : Symbol(T_AB, Decl(unknownControlFlow.ts, 425, 11))
|
||||
}
|
||||
|
||||
// Repro from #51538
|
||||
|
||||
type Left = 'left';
|
||||
>Left : Symbol(Left, Decl(unknownControlFlow.ts, 427, 1))
|
||||
|
||||
type Right = 'right' & { right: 'right' };
|
||||
>Right : Symbol(Right, Decl(unknownControlFlow.ts, 431, 19))
|
||||
>right : Symbol(right, Decl(unknownControlFlow.ts, 432, 24))
|
||||
|
||||
type Either = Left | Right;
|
||||
>Either : Symbol(Either, Decl(unknownControlFlow.ts, 432, 42))
|
||||
>Left : Symbol(Left, Decl(unknownControlFlow.ts, 427, 1))
|
||||
>Right : Symbol(Right, Decl(unknownControlFlow.ts, 431, 19))
|
||||
|
||||
function assertNever(v: never): never {
|
||||
>assertNever : Symbol(assertNever, Decl(unknownControlFlow.ts, 433, 27))
|
||||
>v : Symbol(v, Decl(unknownControlFlow.ts, 435, 21))
|
||||
|
||||
throw new Error('never');
|
||||
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
}
|
||||
|
||||
function fx20(value: Either) {
|
||||
>fx20 : Symbol(fx20, Decl(unknownControlFlow.ts, 437, 1))
|
||||
>value : Symbol(value, Decl(unknownControlFlow.ts, 439, 14))
|
||||
>Either : Symbol(Either, Decl(unknownControlFlow.ts, 432, 42))
|
||||
|
||||
if (value === 'left') {
|
||||
>value : Symbol(value, Decl(unknownControlFlow.ts, 439, 14))
|
||||
|
||||
const foo: 'left' = value;
|
||||
>foo : Symbol(foo, Decl(unknownControlFlow.ts, 441, 13))
|
||||
>value : Symbol(value, Decl(unknownControlFlow.ts, 439, 14))
|
||||
}
|
||||
else if (value === 'right') {
|
||||
>value : Symbol(value, Decl(unknownControlFlow.ts, 439, 14))
|
||||
|
||||
const bar: 'right' = value;
|
||||
>bar : Symbol(bar, Decl(unknownControlFlow.ts, 444, 13))
|
||||
>value : Symbol(value, Decl(unknownControlFlow.ts, 439, 14))
|
||||
}
|
||||
else {
|
||||
assertNever(value);
|
||||
>assertNever : Symbol(assertNever, Decl(unknownControlFlow.ts, 433, 27))
|
||||
>value : Symbol(value, Decl(unknownControlFlow.ts, 439, 14))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1076,3 +1076,55 @@ function x<T_AB extends AB>(x: T_AB & undefined, y: any) {
|
||||
>y : any
|
||||
}
|
||||
|
||||
// Repro from #51538
|
||||
|
||||
type Left = 'left';
|
||||
>Left : "left"
|
||||
|
||||
type Right = 'right' & { right: 'right' };
|
||||
>Right : "right" & { right: 'right'; }
|
||||
>right : "right"
|
||||
|
||||
type Either = Left | Right;
|
||||
>Either : Right | "left"
|
||||
|
||||
function assertNever(v: never): never {
|
||||
>assertNever : (v: never) => never
|
||||
>v : never
|
||||
|
||||
throw new Error('never');
|
||||
>new Error('never') : Error
|
||||
>Error : ErrorConstructor
|
||||
>'never' : "never"
|
||||
}
|
||||
|
||||
function fx20(value: Either) {
|
||||
>fx20 : (value: Either) => void
|
||||
>value : Either
|
||||
|
||||
if (value === 'left') {
|
||||
>value === 'left' : boolean
|
||||
>value : Either
|
||||
>'left' : "left"
|
||||
|
||||
const foo: 'left' = value;
|
||||
>foo : "left"
|
||||
>value : "left"
|
||||
}
|
||||
else if (value === 'right') {
|
||||
>value === 'right' : boolean
|
||||
>value : Right
|
||||
>'right' : "right"
|
||||
|
||||
const bar: 'right' = value;
|
||||
>bar : "right"
|
||||
>value : Right
|
||||
}
|
||||
else {
|
||||
assertNever(value);
|
||||
>assertNever(value) : never
|
||||
>assertNever : (v: never) => never
|
||||
>value : never
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -429,3 +429,25 @@ type AB = "A" | "B";
|
||||
function x<T_AB extends AB>(x: T_AB & undefined, y: any) {
|
||||
let r2: never = y as T_AB & undefined;
|
||||
}
|
||||
|
||||
// Repro from #51538
|
||||
|
||||
type Left = 'left';
|
||||
type Right = 'right' & { right: 'right' };
|
||||
type Either = Left | Right;
|
||||
|
||||
function assertNever(v: never): never {
|
||||
throw new Error('never');
|
||||
}
|
||||
|
||||
function fx20(value: Either) {
|
||||
if (value === 'left') {
|
||||
const foo: 'left' = value;
|
||||
}
|
||||
else if (value === 'right') {
|
||||
const bar: 'right' = value;
|
||||
}
|
||||
else {
|
||||
assertNever(value);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user