mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Narrow by comparisons to boolean literals (#53714)
This commit is contained in:
parent
7d9399e353
commit
1f88596bb1
@ -136,6 +136,7 @@ import {
|
||||
isBlock,
|
||||
isBlockOrCatchScoped,
|
||||
IsBlockScopedContainer,
|
||||
isBooleanLiteral,
|
||||
isCallExpression,
|
||||
isClassStaticBlockDeclaration,
|
||||
isConditionalTypeNode,
|
||||
@ -1279,7 +1280,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
|
||||
case SyntaxKind.EqualsEqualsEqualsToken:
|
||||
case SyntaxKind.ExclamationEqualsEqualsToken:
|
||||
return isNarrowableOperand(expr.left) || isNarrowableOperand(expr.right) ||
|
||||
isNarrowingTypeofOperands(expr.right, expr.left) || isNarrowingTypeofOperands(expr.left, expr.right);
|
||||
isNarrowingTypeofOperands(expr.right, expr.left) || isNarrowingTypeofOperands(expr.left, expr.right) ||
|
||||
(isBooleanLiteral(expr.right) && isNarrowingExpression(expr.left) || isBooleanLiteral(expr.left) && isNarrowingExpression(expr.right));
|
||||
case SyntaxKind.InstanceOfKeyword:
|
||||
return isNarrowableOperand(expr.left);
|
||||
case SyntaxKind.InKeyword:
|
||||
|
||||
@ -34,6 +34,7 @@ import {
|
||||
BigIntLiteral,
|
||||
BigIntLiteralType,
|
||||
BinaryExpression,
|
||||
BinaryOperator,
|
||||
BinaryOperatorToken,
|
||||
binarySearch,
|
||||
BindableObjectDefinePropertyCall,
|
||||
@ -44,6 +45,7 @@ import {
|
||||
BindingPattern,
|
||||
bindSourceFile,
|
||||
Block,
|
||||
BooleanLiteral,
|
||||
BreakOrContinueStatement,
|
||||
CallChain,
|
||||
CallExpression,
|
||||
@ -27661,6 +27663,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return type;
|
||||
}
|
||||
|
||||
function narrowTypeByBooleanComparison(type: Type, expr: Expression, bool: BooleanLiteral, operator: BinaryOperator, assumeTrue: boolean): Type {
|
||||
assumeTrue = (assumeTrue !== (bool.kind === SyntaxKind.TrueKeyword)) !== (operator !== SyntaxKind.ExclamationEqualsEqualsToken && operator !== SyntaxKind.ExclamationEqualsToken);
|
||||
return narrowType(type, expr, assumeTrue);
|
||||
}
|
||||
|
||||
function narrowTypeByBinaryExpression(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
|
||||
switch (expr.operatorToken.kind) {
|
||||
case SyntaxKind.EqualsToken:
|
||||
@ -27709,6 +27716,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (isMatchingConstructorReference(right)) {
|
||||
return narrowTypeByConstructor(type, operator, left, assumeTrue);
|
||||
}
|
||||
if (isBooleanLiteral(right)) {
|
||||
return narrowTypeByBooleanComparison(type, left, right, operator, assumeTrue);
|
||||
}
|
||||
if (isBooleanLiteral(left)) {
|
||||
return narrowTypeByBooleanComparison(type, right, left, operator, assumeTrue);
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.InstanceOfKeyword:
|
||||
return narrowTypeByInstanceof(type, expr, assumeTrue);
|
||||
|
||||
264
tests/baselines/reference/narrowByBooleanComparison.symbols
Normal file
264
tests/baselines/reference/narrowByBooleanComparison.symbols
Normal file
@ -0,0 +1,264 @@
|
||||
//// [tests/cases/compiler/narrowByBooleanComparison.ts] ////
|
||||
|
||||
=== narrowByBooleanComparison.ts ===
|
||||
type A = { type: "A" };
|
||||
>A : Symbol(A, Decl(narrowByBooleanComparison.ts, 0, 0))
|
||||
>type : Symbol(type, Decl(narrowByBooleanComparison.ts, 0, 10))
|
||||
|
||||
type B = { type: "B" };
|
||||
>B : Symbol(B, Decl(narrowByBooleanComparison.ts, 0, 23))
|
||||
>type : Symbol(type, Decl(narrowByBooleanComparison.ts, 1, 10))
|
||||
|
||||
type C = { type: "C" };
|
||||
>C : Symbol(C, Decl(narrowByBooleanComparison.ts, 1, 23))
|
||||
>type : Symbol(type, Decl(narrowByBooleanComparison.ts, 2, 10))
|
||||
|
||||
type MyUnion = A | B | C;
|
||||
>MyUnion : Symbol(MyUnion, Decl(narrowByBooleanComparison.ts, 2, 23))
|
||||
>A : Symbol(A, Decl(narrowByBooleanComparison.ts, 0, 0))
|
||||
>B : Symbol(B, Decl(narrowByBooleanComparison.ts, 0, 23))
|
||||
>C : Symbol(C, Decl(narrowByBooleanComparison.ts, 1, 23))
|
||||
|
||||
const isA = (x: MyUnion): x is A => x.type === "A";
|
||||
>isA : Symbol(isA, Decl(narrowByBooleanComparison.ts, 5, 5))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 5, 13))
|
||||
>MyUnion : Symbol(MyUnion, Decl(narrowByBooleanComparison.ts, 2, 23))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 5, 13))
|
||||
>A : Symbol(A, Decl(narrowByBooleanComparison.ts, 0, 0))
|
||||
>x.type : Symbol(type, Decl(narrowByBooleanComparison.ts, 0, 10), Decl(narrowByBooleanComparison.ts, 1, 10), Decl(narrowByBooleanComparison.ts, 2, 10))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 5, 13))
|
||||
>type : Symbol(type, Decl(narrowByBooleanComparison.ts, 0, 10), Decl(narrowByBooleanComparison.ts, 1, 10), Decl(narrowByBooleanComparison.ts, 2, 10))
|
||||
|
||||
function test1(x: MyUnion) {
|
||||
>test1 : Symbol(test1, Decl(narrowByBooleanComparison.ts, 5, 51))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 7, 15))
|
||||
>MyUnion : Symbol(MyUnion, Decl(narrowByBooleanComparison.ts, 2, 23))
|
||||
|
||||
if (isA(x) !== true) {
|
||||
>isA : Symbol(isA, Decl(narrowByBooleanComparison.ts, 5, 5))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 7, 15))
|
||||
|
||||
x;
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 7, 15))
|
||||
}
|
||||
|
||||
if (isA(x) !== false) {
|
||||
>isA : Symbol(isA, Decl(narrowByBooleanComparison.ts, 5, 5))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 7, 15))
|
||||
|
||||
x;
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 7, 15))
|
||||
}
|
||||
|
||||
if (isA(x) === false) {
|
||||
>isA : Symbol(isA, Decl(narrowByBooleanComparison.ts, 5, 5))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 7, 15))
|
||||
|
||||
x;
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 7, 15))
|
||||
}
|
||||
|
||||
if (isA(x) === true) {
|
||||
>isA : Symbol(isA, Decl(narrowByBooleanComparison.ts, 5, 5))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 7, 15))
|
||||
|
||||
x;
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 7, 15))
|
||||
}
|
||||
|
||||
if (isA(x) != true) {
|
||||
>isA : Symbol(isA, Decl(narrowByBooleanComparison.ts, 5, 5))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 7, 15))
|
||||
|
||||
x;
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 7, 15))
|
||||
}
|
||||
|
||||
if (isA(x) == true) {
|
||||
>isA : Symbol(isA, Decl(narrowByBooleanComparison.ts, 5, 5))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 7, 15))
|
||||
|
||||
x;
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 7, 15))
|
||||
}
|
||||
|
||||
if (true !== isA(x)) {
|
||||
>isA : Symbol(isA, Decl(narrowByBooleanComparison.ts, 5, 5))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 7, 15))
|
||||
|
||||
x;
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 7, 15))
|
||||
}
|
||||
|
||||
if (true === isA(x)) {
|
||||
>isA : Symbol(isA, Decl(narrowByBooleanComparison.ts, 5, 5))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 7, 15))
|
||||
|
||||
x;
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 7, 15))
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/53093
|
||||
function test2(x: unknown) {
|
||||
>test2 : Symbol(test2, Decl(narrowByBooleanComparison.ts, 39, 1))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 42, 15))
|
||||
|
||||
if (x instanceof Error === false) {
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 42, 15))
|
||||
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
return;
|
||||
}
|
||||
x;
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 42, 15))
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/50712
|
||||
function test3(foo: unknown) {
|
||||
>test3 : Symbol(test3, Decl(narrowByBooleanComparison.ts, 47, 1))
|
||||
>foo : Symbol(foo, Decl(narrowByBooleanComparison.ts, 50, 15))
|
||||
|
||||
if (typeof foo !== 'string' && Array.isArray(foo) === false) {
|
||||
>foo : Symbol(foo, Decl(narrowByBooleanComparison.ts, 50, 15))
|
||||
>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
|
||||
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
|
||||
>foo : Symbol(foo, Decl(narrowByBooleanComparison.ts, 50, 15))
|
||||
|
||||
throw new Error('Not a string or an array');
|
||||
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
}
|
||||
foo;
|
||||
>foo : Symbol(foo, Decl(narrowByBooleanComparison.ts, 50, 15))
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/55395
|
||||
class WebError extends URIError {
|
||||
>WebError : Symbol(WebError, Decl(narrowByBooleanComparison.ts, 55, 1))
|
||||
>URIError : Symbol(URIError, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
status?: number;
|
||||
>status : Symbol(WebError.status, Decl(narrowByBooleanComparison.ts, 58, 33))
|
||||
}
|
||||
function test4() {
|
||||
>test4 : Symbol(test4, Decl(narrowByBooleanComparison.ts, 60, 1))
|
||||
|
||||
try {
|
||||
// make a request
|
||||
} catch (err) {
|
||||
>err : Symbol(err, Decl(narrowByBooleanComparison.ts, 64, 13))
|
||||
|
||||
if (err instanceof WebError === false || err.status != 401) {
|
||||
>err : Symbol(err, Decl(narrowByBooleanComparison.ts, 64, 13))
|
||||
>WebError : Symbol(WebError, Decl(narrowByBooleanComparison.ts, 55, 1))
|
||||
>err.status : Symbol(WebError.status, Decl(narrowByBooleanComparison.ts, 58, 33))
|
||||
>err : Symbol(err, Decl(narrowByBooleanComparison.ts, 64, 13))
|
||||
>status : Symbol(WebError.status, Decl(narrowByBooleanComparison.ts, 58, 33))
|
||||
|
||||
console.error(err);
|
||||
>console.error : Symbol(Console.error, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>error : Symbol(Console.error, Decl(lib.dom.d.ts, --, --))
|
||||
>err : Symbol(err, Decl(narrowByBooleanComparison.ts, 64, 13))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/44366
|
||||
interface Entity {
|
||||
>Entity : Symbol(Entity, Decl(narrowByBooleanComparison.ts, 69, 1))
|
||||
|
||||
type: string;
|
||||
>type : Symbol(Entity.type, Decl(narrowByBooleanComparison.ts, 72, 18))
|
||||
}
|
||||
const ACTOR_TYPE = "actor";
|
||||
>ACTOR_TYPE : Symbol(ACTOR_TYPE, Decl(narrowByBooleanComparison.ts, 75, 5))
|
||||
|
||||
interface Actor extends Entity {
|
||||
>Actor : Symbol(Actor, Decl(narrowByBooleanComparison.ts, 75, 27))
|
||||
>Entity : Symbol(Entity, Decl(narrowByBooleanComparison.ts, 69, 1))
|
||||
|
||||
type: typeof ACTOR_TYPE;
|
||||
>type : Symbol(Actor.type, Decl(narrowByBooleanComparison.ts, 76, 32))
|
||||
>ACTOR_TYPE : Symbol(ACTOR_TYPE, Decl(narrowByBooleanComparison.ts, 75, 5))
|
||||
}
|
||||
function isActor(entity: Entity): entity is Actor {
|
||||
>isActor : Symbol(isActor, Decl(narrowByBooleanComparison.ts, 78, 1))
|
||||
>entity : Symbol(entity, Decl(narrowByBooleanComparison.ts, 79, 17))
|
||||
>Entity : Symbol(Entity, Decl(narrowByBooleanComparison.ts, 69, 1))
|
||||
>entity : Symbol(entity, Decl(narrowByBooleanComparison.ts, 79, 17))
|
||||
>Actor : Symbol(Actor, Decl(narrowByBooleanComparison.ts, 75, 27))
|
||||
|
||||
return entity.type === ACTOR_TYPE;
|
||||
>entity.type : Symbol(Entity.type, Decl(narrowByBooleanComparison.ts, 72, 18))
|
||||
>entity : Symbol(entity, Decl(narrowByBooleanComparison.ts, 79, 17))
|
||||
>type : Symbol(Entity.type, Decl(narrowByBooleanComparison.ts, 72, 18))
|
||||
>ACTOR_TYPE : Symbol(ACTOR_TYPE, Decl(narrowByBooleanComparison.ts, 75, 5))
|
||||
}
|
||||
function test5(bin: Entity) {
|
||||
>test5 : Symbol(test5, Decl(narrowByBooleanComparison.ts, 81, 1))
|
||||
>bin : Symbol(bin, Decl(narrowByBooleanComparison.ts, 82, 15))
|
||||
>Entity : Symbol(Entity, Decl(narrowByBooleanComparison.ts, 69, 1))
|
||||
|
||||
if (isActor(bin) === false) {
|
||||
>isActor : Symbol(isActor, Decl(narrowByBooleanComparison.ts, 78, 1))
|
||||
>bin : Symbol(bin, Decl(narrowByBooleanComparison.ts, 82, 15))
|
||||
|
||||
bin;
|
||||
>bin : Symbol(bin, Decl(narrowByBooleanComparison.ts, 82, 15))
|
||||
|
||||
} else {
|
||||
bin;
|
||||
>bin : Symbol(bin, Decl(narrowByBooleanComparison.ts, 82, 15))
|
||||
}
|
||||
}
|
||||
function test6(bin: Entity) {
|
||||
>test6 : Symbol(test6, Decl(narrowByBooleanComparison.ts, 88, 1))
|
||||
>bin : Symbol(bin, Decl(narrowByBooleanComparison.ts, 89, 15))
|
||||
>Entity : Symbol(Entity, Decl(narrowByBooleanComparison.ts, 69, 1))
|
||||
|
||||
if (isActor(bin) == false) {
|
||||
>isActor : Symbol(isActor, Decl(narrowByBooleanComparison.ts, 78, 1))
|
||||
>bin : Symbol(bin, Decl(narrowByBooleanComparison.ts, 89, 15))
|
||||
|
||||
bin;
|
||||
>bin : Symbol(bin, Decl(narrowByBooleanComparison.ts, 89, 15))
|
||||
|
||||
} else {
|
||||
bin;
|
||||
>bin : Symbol(bin, Decl(narrowByBooleanComparison.ts, 89, 15))
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/53005
|
||||
function isFunction(x: unknown): x is Function {
|
||||
>isFunction : Symbol(isFunction, Decl(narrowByBooleanComparison.ts, 95, 1))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 98, 20))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 98, 20))
|
||||
>Function : Symbol(Function, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
return typeof x === "function";
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 98, 20))
|
||||
}
|
||||
|
||||
function test7(x: unknown) {
|
||||
>test7 : Symbol(test7, Decl(narrowByBooleanComparison.ts, 100, 1))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 102, 15))
|
||||
|
||||
if (isFunction(x) !== false) {
|
||||
>isFunction : Symbol(isFunction, Decl(narrowByBooleanComparison.ts, 95, 1))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 102, 15))
|
||||
|
||||
x;
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 102, 15))
|
||||
}
|
||||
if (isFunction(x) === true) {
|
||||
>isFunction : Symbol(isFunction, Decl(narrowByBooleanComparison.ts, 95, 1))
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 102, 15))
|
||||
|
||||
x;
|
||||
>x : Symbol(x, Decl(narrowByBooleanComparison.ts, 102, 15))
|
||||
}
|
||||
}
|
||||
|
||||
308
tests/baselines/reference/narrowByBooleanComparison.types
Normal file
308
tests/baselines/reference/narrowByBooleanComparison.types
Normal file
@ -0,0 +1,308 @@
|
||||
//// [tests/cases/compiler/narrowByBooleanComparison.ts] ////
|
||||
|
||||
=== narrowByBooleanComparison.ts ===
|
||||
type A = { type: "A" };
|
||||
>A : { type: "A"; }
|
||||
>type : "A"
|
||||
|
||||
type B = { type: "B" };
|
||||
>B : { type: "B"; }
|
||||
>type : "B"
|
||||
|
||||
type C = { type: "C" };
|
||||
>C : { type: "C"; }
|
||||
>type : "C"
|
||||
|
||||
type MyUnion = A | B | C;
|
||||
>MyUnion : A | B | C
|
||||
|
||||
const isA = (x: MyUnion): x is A => x.type === "A";
|
||||
>isA : (x: MyUnion) => x is A
|
||||
>(x: MyUnion): x is A => x.type === "A" : (x: MyUnion) => x is A
|
||||
>x : MyUnion
|
||||
>x.type === "A" : boolean
|
||||
>x.type : "A" | "B" | "C"
|
||||
>x : MyUnion
|
||||
>type : "A" | "B" | "C"
|
||||
>"A" : "A"
|
||||
|
||||
function test1(x: MyUnion) {
|
||||
>test1 : (x: MyUnion) => void
|
||||
>x : MyUnion
|
||||
|
||||
if (isA(x) !== true) {
|
||||
>isA(x) !== true : boolean
|
||||
>isA(x) : boolean
|
||||
>isA : (x: MyUnion) => x is A
|
||||
>x : MyUnion
|
||||
>true : true
|
||||
|
||||
x;
|
||||
>x : B | C
|
||||
}
|
||||
|
||||
if (isA(x) !== false) {
|
||||
>isA(x) !== false : boolean
|
||||
>isA(x) : boolean
|
||||
>isA : (x: MyUnion) => x is A
|
||||
>x : MyUnion
|
||||
>false : false
|
||||
|
||||
x;
|
||||
>x : A
|
||||
}
|
||||
|
||||
if (isA(x) === false) {
|
||||
>isA(x) === false : boolean
|
||||
>isA(x) : boolean
|
||||
>isA : (x: MyUnion) => x is A
|
||||
>x : MyUnion
|
||||
>false : false
|
||||
|
||||
x;
|
||||
>x : B | C
|
||||
}
|
||||
|
||||
if (isA(x) === true) {
|
||||
>isA(x) === true : boolean
|
||||
>isA(x) : boolean
|
||||
>isA : (x: MyUnion) => x is A
|
||||
>x : MyUnion
|
||||
>true : true
|
||||
|
||||
x;
|
||||
>x : A
|
||||
}
|
||||
|
||||
if (isA(x) != true) {
|
||||
>isA(x) != true : boolean
|
||||
>isA(x) : boolean
|
||||
>isA : (x: MyUnion) => x is A
|
||||
>x : MyUnion
|
||||
>true : true
|
||||
|
||||
x;
|
||||
>x : B | C
|
||||
}
|
||||
|
||||
if (isA(x) == true) {
|
||||
>isA(x) == true : boolean
|
||||
>isA(x) : boolean
|
||||
>isA : (x: MyUnion) => x is A
|
||||
>x : MyUnion
|
||||
>true : true
|
||||
|
||||
x;
|
||||
>x : A
|
||||
}
|
||||
|
||||
if (true !== isA(x)) {
|
||||
>true !== isA(x) : boolean
|
||||
>true : true
|
||||
>isA(x) : boolean
|
||||
>isA : (x: MyUnion) => x is A
|
||||
>x : MyUnion
|
||||
|
||||
x;
|
||||
>x : B | C
|
||||
}
|
||||
|
||||
if (true === isA(x)) {
|
||||
>true === isA(x) : boolean
|
||||
>true : true
|
||||
>isA(x) : boolean
|
||||
>isA : (x: MyUnion) => x is A
|
||||
>x : MyUnion
|
||||
|
||||
x;
|
||||
>x : A
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/53093
|
||||
function test2(x: unknown) {
|
||||
>test2 : (x: unknown) => void
|
||||
>x : unknown
|
||||
|
||||
if (x instanceof Error === false) {
|
||||
>x instanceof Error === false : boolean
|
||||
>x instanceof Error : boolean
|
||||
>x : unknown
|
||||
>Error : ErrorConstructor
|
||||
>false : false
|
||||
|
||||
return;
|
||||
}
|
||||
x;
|
||||
>x : Error
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/50712
|
||||
function test3(foo: unknown) {
|
||||
>test3 : (foo: unknown) => void
|
||||
>foo : unknown
|
||||
|
||||
if (typeof foo !== 'string' && Array.isArray(foo) === false) {
|
||||
>typeof foo !== 'string' && Array.isArray(foo) === false : boolean
|
||||
>typeof foo !== 'string' : boolean
|
||||
>typeof foo : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
>foo : unknown
|
||||
>'string' : "string"
|
||||
>Array.isArray(foo) === false : boolean
|
||||
>Array.isArray(foo) : boolean
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
>foo : unknown
|
||||
>false : false
|
||||
|
||||
throw new Error('Not a string or an array');
|
||||
>new Error('Not a string or an array') : Error
|
||||
>Error : ErrorConstructor
|
||||
>'Not a string or an array' : "Not a string or an array"
|
||||
}
|
||||
foo;
|
||||
>foo : string | any[]
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/55395
|
||||
class WebError extends URIError {
|
||||
>WebError : WebError
|
||||
>URIError : URIError
|
||||
|
||||
status?: number;
|
||||
>status : number | undefined
|
||||
}
|
||||
function test4() {
|
||||
>test4 : () => void
|
||||
|
||||
try {
|
||||
// make a request
|
||||
} catch (err) {
|
||||
>err : unknown
|
||||
|
||||
if (err instanceof WebError === false || err.status != 401) {
|
||||
>err instanceof WebError === false || err.status != 401 : boolean
|
||||
>err instanceof WebError === false : boolean
|
||||
>err instanceof WebError : boolean
|
||||
>err : unknown
|
||||
>WebError : typeof WebError
|
||||
>false : false
|
||||
>err.status != 401 : boolean
|
||||
>err.status : number | undefined
|
||||
>err : WebError
|
||||
>status : number | undefined
|
||||
>401 : 401
|
||||
|
||||
console.error(err);
|
||||
>console.error(err) : void
|
||||
>console.error : (...data: any[]) => void
|
||||
>console : Console
|
||||
>error : (...data: any[]) => void
|
||||
>err : unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/44366
|
||||
interface Entity {
|
||||
type: string;
|
||||
>type : string
|
||||
}
|
||||
const ACTOR_TYPE = "actor";
|
||||
>ACTOR_TYPE : "actor"
|
||||
>"actor" : "actor"
|
||||
|
||||
interface Actor extends Entity {
|
||||
type: typeof ACTOR_TYPE;
|
||||
>type : "actor"
|
||||
>ACTOR_TYPE : "actor"
|
||||
}
|
||||
function isActor(entity: Entity): entity is Actor {
|
||||
>isActor : (entity: Entity) => entity is Actor
|
||||
>entity : Entity
|
||||
|
||||
return entity.type === ACTOR_TYPE;
|
||||
>entity.type === ACTOR_TYPE : boolean
|
||||
>entity.type : string
|
||||
>entity : Entity
|
||||
>type : string
|
||||
>ACTOR_TYPE : "actor"
|
||||
}
|
||||
function test5(bin: Entity) {
|
||||
>test5 : (bin: Entity) => void
|
||||
>bin : Entity
|
||||
|
||||
if (isActor(bin) === false) {
|
||||
>isActor(bin) === false : boolean
|
||||
>isActor(bin) : boolean
|
||||
>isActor : (entity: Entity) => entity is Actor
|
||||
>bin : Entity
|
||||
>false : false
|
||||
|
||||
bin;
|
||||
>bin : Entity
|
||||
|
||||
} else {
|
||||
bin;
|
||||
>bin : Actor
|
||||
}
|
||||
}
|
||||
function test6(bin: Entity) {
|
||||
>test6 : (bin: Entity) => void
|
||||
>bin : Entity
|
||||
|
||||
if (isActor(bin) == false) {
|
||||
>isActor(bin) == false : boolean
|
||||
>isActor(bin) : boolean
|
||||
>isActor : (entity: Entity) => entity is Actor
|
||||
>bin : Entity
|
||||
>false : false
|
||||
|
||||
bin;
|
||||
>bin : Entity
|
||||
|
||||
} else {
|
||||
bin;
|
||||
>bin : Actor
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/53005
|
||||
function isFunction(x: unknown): x is Function {
|
||||
>isFunction : (x: unknown) => x is Function
|
||||
>x : unknown
|
||||
|
||||
return typeof x === "function";
|
||||
>typeof x === "function" : boolean
|
||||
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
>x : unknown
|
||||
>"function" : "function"
|
||||
}
|
||||
|
||||
function test7(x: unknown) {
|
||||
>test7 : (x: unknown) => void
|
||||
>x : unknown
|
||||
|
||||
if (isFunction(x) !== false) {
|
||||
>isFunction(x) !== false : boolean
|
||||
>isFunction(x) : boolean
|
||||
>isFunction : (x: unknown) => x is Function
|
||||
>x : unknown
|
||||
>false : false
|
||||
|
||||
x;
|
||||
>x : Function
|
||||
}
|
||||
if (isFunction(x) === true) {
|
||||
>isFunction(x) === true : boolean
|
||||
>isFunction(x) : boolean
|
||||
>isFunction : (x: unknown) => x is Function
|
||||
>x : unknown
|
||||
>true : true
|
||||
|
||||
x;
|
||||
>x : Function
|
||||
}
|
||||
}
|
||||
|
||||
113
tests/cases/compiler/narrowByBooleanComparison.ts
Normal file
113
tests/cases/compiler/narrowByBooleanComparison.ts
Normal file
@ -0,0 +1,113 @@
|
||||
// @strict: true
|
||||
// @noEmit: true
|
||||
|
||||
type A = { type: "A" };
|
||||
type B = { type: "B" };
|
||||
type C = { type: "C" };
|
||||
type MyUnion = A | B | C;
|
||||
|
||||
const isA = (x: MyUnion): x is A => x.type === "A";
|
||||
|
||||
function test1(x: MyUnion) {
|
||||
if (isA(x) !== true) {
|
||||
x;
|
||||
}
|
||||
|
||||
if (isA(x) !== false) {
|
||||
x;
|
||||
}
|
||||
|
||||
if (isA(x) === false) {
|
||||
x;
|
||||
}
|
||||
|
||||
if (isA(x) === true) {
|
||||
x;
|
||||
}
|
||||
|
||||
if (isA(x) != true) {
|
||||
x;
|
||||
}
|
||||
|
||||
if (isA(x) == true) {
|
||||
x;
|
||||
}
|
||||
|
||||
if (true !== isA(x)) {
|
||||
x;
|
||||
}
|
||||
|
||||
if (true === isA(x)) {
|
||||
x;
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/53093
|
||||
function test2(x: unknown) {
|
||||
if (x instanceof Error === false) {
|
||||
return;
|
||||
}
|
||||
x;
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/50712
|
||||
function test3(foo: unknown) {
|
||||
if (typeof foo !== 'string' && Array.isArray(foo) === false) {
|
||||
throw new Error('Not a string or an array');
|
||||
}
|
||||
foo;
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/55395
|
||||
class WebError extends URIError {
|
||||
status?: number;
|
||||
}
|
||||
function test4() {
|
||||
try {
|
||||
// make a request
|
||||
} catch (err) {
|
||||
if (err instanceof WebError === false || err.status != 401) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/44366
|
||||
interface Entity {
|
||||
type: string;
|
||||
}
|
||||
const ACTOR_TYPE = "actor";
|
||||
interface Actor extends Entity {
|
||||
type: typeof ACTOR_TYPE;
|
||||
}
|
||||
function isActor(entity: Entity): entity is Actor {
|
||||
return entity.type === ACTOR_TYPE;
|
||||
}
|
||||
function test5(bin: Entity) {
|
||||
if (isActor(bin) === false) {
|
||||
bin;
|
||||
} else {
|
||||
bin;
|
||||
}
|
||||
}
|
||||
function test6(bin: Entity) {
|
||||
if (isActor(bin) == false) {
|
||||
bin;
|
||||
} else {
|
||||
bin;
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/microsoft/TypeScript/issues/53005
|
||||
function isFunction(x: unknown): x is Function {
|
||||
return typeof x === "function";
|
||||
}
|
||||
|
||||
function test7(x: unknown) {
|
||||
if (isFunction(x) !== false) {
|
||||
x;
|
||||
}
|
||||
if (isFunction(x) === true) {
|
||||
x;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user