Narrow by comparisons to boolean literals (#53714)

This commit is contained in:
Mateusz Burzyński 2023-09-19 22:38:31 +02:00 committed by GitHub
parent 7d9399e353
commit 1f88596bb1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 701 additions and 1 deletions

View File

@ -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:

View File

@ -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);

View 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))
}
}

View 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
}
}

View 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;
}
}