Improve uncalled function check related to parenthesized and binary expressions (#50756)

fixes https://github.com/microsoft/TypeScript/issues/37598
This commit is contained in:
Mateusz Burzyński 2023-01-17 21:22:16 +00:00 committed by GitHub
parent f6fc444b33
commit 16c695cdbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 989 additions and 163 deletions

View File

@ -172,7 +172,10 @@ import {
isJSDocTypeAlias,
isJsonSourceFile,
isLeftHandSideExpression,
isLogicalOrCoalescingAssignmentExpression,
isLogicalOrCoalescingAssignmentOperator,
isLogicalOrCoalescingBinaryExpression,
isLogicalOrCoalescingBinaryOperator,
isModuleAugmentationExternal,
isModuleBlock,
isModuleDeclaration,
@ -1377,17 +1380,13 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
node = (node as PrefixUnaryExpression).operand;
}
else {
return node.kind === SyntaxKind.BinaryExpression && (
(node as BinaryExpression).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken ||
(node as BinaryExpression).operatorToken.kind === SyntaxKind.BarBarToken ||
(node as BinaryExpression).operatorToken.kind === SyntaxKind.QuestionQuestionToken);
return isLogicalOrCoalescingBinaryExpression(node);
}
}
}
function isLogicalAssignmentExpression(node: Node) {
node = skipParentheses(node);
return isBinaryExpression(node) && isLogicalOrCoalescingAssignmentOperator(node.operatorToken.kind);
return isLogicalOrCoalescingAssignmentExpression(skipParentheses(node));
}
function isTopLevelLogicalExpression(node: Node): boolean {
@ -1859,10 +1858,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
// we'll need to handle the `bindLogicalExpression` scenarios in this state machine, too
// For now, though, since the common cases are chained `+`, leaving it recursive is fine
const operator = node.operatorToken.kind;
if (operator === SyntaxKind.AmpersandAmpersandToken ||
operator === SyntaxKind.BarBarToken ||
operator === SyntaxKind.QuestionQuestionToken ||
isLogicalOrCoalescingAssignmentOperator(operator)) {
if (isLogicalOrCoalescingBinaryOperator(operator) || isLogicalOrCoalescingAssignmentOperator(operator)) {
if (isTopLevelLogicalExpression(node)) {
const postExpressionLabel = createBranchLabel();
bindLogicalLikeExpression(node, postExpressionLabel, postExpressionLabel);

View File

@ -591,6 +591,8 @@ import {
isLiteralExpressionOfObject,
isLiteralImportTypeNode,
isLiteralTypeNode,
isLogicalOrCoalescingBinaryExpression,
isLogicalOrCoalescingBinaryOperator,
isMetaProperty,
isMethodDeclaration,
isMethodSignature,
@ -35561,13 +35563,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
setLeftType(state, leftType);
setLastResult(state, /*type*/ undefined);
const operator = operatorToken.kind;
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) {
if (operator === SyntaxKind.AmpersandAmpersandToken) {
let parent = node.parent;
while (parent.kind === SyntaxKind.ParenthesizedExpression
|| isBinaryExpression(parent) && (parent.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken || parent.operatorToken.kind === SyntaxKind.BarBarToken)) {
parent = parent.parent;
}
if (isLogicalOrCoalescingBinaryOperator(operator)) {
let parent = node.parent;
while (parent.kind === SyntaxKind.ParenthesizedExpression || isLogicalOrCoalescingBinaryExpression(parent)) {
parent = parent.parent;
}
if (operator === SyntaxKind.AmpersandAmpersandToken || isIfStatement(parent)) {
checkTestingKnownTruthyCallableOrAwaitableType(node.left, leftType, isIfStatement(parent) ? parent.thenStatement : undefined);
}
checkTruthinessOfType(leftType, node.left);
@ -35656,7 +35657,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return checkDestructuringAssignment(left, checkExpression(right, checkMode), checkMode, right.kind === SyntaxKind.ThisKeyword);
}
let leftType: Type;
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) {
if (isLogicalOrCoalescingBinaryOperator(operator)) {
leftType = checkTruthinessExpression(left, checkMode);
}
else {
@ -39921,19 +39922,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
function checkTestingKnownTruthyCallableOrAwaitableType(condExpr: Expression, condType: Type, body?: Statement | Expression) {
if (!strictNullChecks) return;
bothHelper(condExpr, body);
function bothHelper(condExpr: Expression, body: Expression | Statement | undefined) {
condExpr = skipParentheses(condExpr);
helper(condExpr, body);
while (isBinaryExpression(condExpr) && condExpr.operatorToken.kind === SyntaxKind.BarBarToken) {
condExpr = condExpr.left;
helper(condExpr, body);
while (isBinaryExpression(condExpr) && (condExpr.operatorToken.kind === SyntaxKind.BarBarToken || condExpr.operatorToken.kind === SyntaxKind.QuestionQuestionToken)) {
condExpr = skipParentheses(condExpr.left);
helper(condExpr, body);
}
}
function helper(condExpr: Expression, body: Expression | Statement | undefined) {
const location = isBinaryExpression(condExpr) &&
(condExpr.operatorToken.kind === SyntaxKind.BarBarToken || condExpr.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken)
? condExpr.right
: condExpr;
if (isModuleExportsAccessExpression(location)) return;
const location = isLogicalOrCoalescingBinaryExpression(condExpr) ? skipParentheses(condExpr.right) : condExpr;
if (isModuleExportsAccessExpression(location)) {
return;
}
if (isLogicalOrCoalescingBinaryExpression(location)) {
bothHelper(location, body);
return;
}
const type = location === condExpr ? condType : checkTruthinessExpression(location);
const isPropertyExpressionCast = isPropertyAccessExpression(location) && isTypeAssertion(location.expression);
if (!(getTypeFacts(type) & TypeFacts.Truthy) || isPropertyExpressionCast) return;
@ -39951,7 +39961,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const testedNode = isIdentifier(location) ? location
: isPropertyAccessExpression(location) ? location.name
: isBinaryExpression(location) && isIdentifier(location.right) ? location.right
: undefined;
const testedSymbol = testedNode && getSymbolAtLocation(testedNode);
if (!testedSymbol && !isPromise) {

View File

@ -1,6 +1,5 @@
import {
AssignmentExpression,
BinaryExpression,
Bundle,
chainBundle,
getNonAssignmentOperatorForCompoundAssignment,
@ -14,7 +13,6 @@ import {
Node,
skipParentheses,
SourceFile,
SyntaxKind,
Token,
TransformationContext,
TransformFlags,
@ -43,16 +41,10 @@ export function transformES2021(context: TransformationContext): (x: SourceFile
if ((node.transformFlags & TransformFlags.ContainsES2021) === 0) {
return node;
}
switch (node.kind) {
case SyntaxKind.BinaryExpression:
const binaryExpression = node as BinaryExpression;
if (isLogicalOrCoalescingAssignmentExpression(binaryExpression)) {
return transformLogicalAssignment(binaryExpression);
}
// falls through
default:
return visitEachChild(node, visitor, context);
if (isLogicalOrCoalescingAssignmentExpression(node)) {
return transformLogicalAssignment(node);
}
return visitEachChild(node, visitor, context);
}
function transformLogicalAssignment(binaryExpression: AssignmentExpression<Token<LogicalOrCoalescingAssignmentOperator>>): VisitResult<Node> {

View File

@ -362,6 +362,7 @@ import {
LiteralImportTypeNode,
LiteralLikeElementAccessExpression,
LiteralLikeNode,
LogicalOperator,
LogicalOrCoalescingAssignmentOperator,
map,
mapDefined,
@ -6246,11 +6247,13 @@ export function modifierToFlag(token: SyntaxKind): ModifierFlags {
return ModifierFlags.None;
}
function isBinaryLogicalOperator(token: SyntaxKind): boolean {
return token === SyntaxKind.BarBarToken || token === SyntaxKind.AmpersandAmpersandToken;
}
/** @internal */
export function isLogicalOperator(token: SyntaxKind): boolean {
return token === SyntaxKind.BarBarToken
|| token === SyntaxKind.AmpersandAmpersandToken
|| token === SyntaxKind.ExclamationToken;
return isBinaryLogicalOperator(token) || token === SyntaxKind.ExclamationToken;
}
/** @internal */
@ -6261,8 +6264,18 @@ export function isLogicalOrCoalescingAssignmentOperator(token: SyntaxKind): toke
}
/** @internal */
export function isLogicalOrCoalescingAssignmentExpression(expr: BinaryExpression): expr is AssignmentExpression<Token<LogicalOrCoalescingAssignmentOperator>> {
return isLogicalOrCoalescingAssignmentOperator(expr.operatorToken.kind);
export function isLogicalOrCoalescingAssignmentExpression(expr: Node): expr is AssignmentExpression<Token<LogicalOrCoalescingAssignmentOperator>> {
return isBinaryExpression(expr) && isLogicalOrCoalescingAssignmentOperator(expr.operatorToken.kind);
}
/** @internal */
export function isLogicalOrCoalescingBinaryOperator(token: SyntaxKind): token is LogicalOperator | SyntaxKind.QuestionQuestionToken {
return isBinaryLogicalOperator(token) || token === SyntaxKind.QuestionQuestionToken;
}
/** @internal */
export function isLogicalOrCoalescingBinaryExpression(expr: Node): expr is BinaryExpression {
return isBinaryExpression(expr) && isLogicalOrCoalescingBinaryOperator(expr.operatorToken.kind);
}
/** @internal */

View File

@ -2,16 +2,40 @@ tests/cases/compiler/truthinessCallExpressionCoercion2.ts(11,5): error TS2774: T
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(14,10): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(41,18): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(44,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(48,11): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(65,46): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(76,5): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(79,10): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(99,5): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(109,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(112,14): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(48,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(52,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(52,22): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(56,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(60,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(60,22): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(64,11): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(93,10): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(97,15): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(97,28): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(101,10): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(101,23): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(105,15): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(105,28): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(109,10): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(109,23): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(116,46): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(127,5): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(130,10): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(150,5): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(153,10): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(157,15): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(157,27): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(161,10): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(161,22): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(165,15): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(165,27): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(169,10): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(169,22): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(180,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(183,14): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
==== tests/cases/compiler/truthinessCallExpressionCoercion2.ts (11 errors) ====
==== tests/cases/compiler/truthinessCallExpressionCoercion2.ts (35 errors) ====
declare class A {
static from(): string;
}
@ -66,6 +90,34 @@ tests/cases/compiler/truthinessCallExpressionCoercion2.ts(112,14): error TS2774:
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
}
// error
if (required1 || b) {
~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
}
// error
if (required1 || required2) {
~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
}
// error
if (required1 ?? b) {
~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
}
// error
if (required1 ?? required2) {
~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
}
// error
if (((required1 && b))) {
~~~~~~~~~
@ -77,10 +129,63 @@ tests/cases/compiler/truthinessCallExpressionCoercion2.ts(112,14): error TS2774:
required1();
}
// ok
if (required1 || b) {
required1();
}
// ok
if (required1 ?? b) {
required1();
}
// ok
if (b ?? required1) {
required1();
}
// ok
if (((required1 && b))) {
required1();
}
// error, extra parens are on purpose here
if ((required1)) {
~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
}
// error
if (b && (required1 || required2)) {
~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
}
// error
if ((required1 || required2) && b) {
~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
}
// error
if (b && (required1 ?? required2)) {
~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
}
// error
if ((required1 ?? required2) && b) {
~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
}
}
function checksConsole() {
@ -129,6 +234,44 @@ tests/cases/compiler/truthinessCallExpressionCoercion2.ts(112,14): error TS2774:
x1.a.b.c && x2.a.b.c();
~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
// error, extra parens are on purpose here
if ((x1.a.b.c)) {
~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
}
// error
if (1 && (x1.a.b.c || x2.a.b.c)) {
~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
}
// error
if ((x1.a.b.c || x2.a.b.c) && 1) {
~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
}
// error
if (1 && (x1.a.b.c ?? x2.a.b.c)) {
~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
}
// error
if ((x1.a.b.c ?? x2.a.b.c) && 1) {
~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
}
}
class Foo {

View File

@ -45,6 +45,22 @@ function test(required1: () => boolean, required2: () => boolean, b: boolean, op
if (required1 && b) {
}
// error
if (required1 || b) {
}
// error
if (required1 || required2) {
}
// error
if (required1 ?? b) {
}
// error
if (required1 ?? required2) {
}
// error
if (((required1 && b))) {
}
@ -54,10 +70,45 @@ function test(required1: () => boolean, required2: () => boolean, b: boolean, op
required1();
}
// ok
if (required1 || b) {
required1();
}
// ok
if (required1 ?? b) {
required1();
}
// ok
if (b ?? required1) {
required1();
}
// ok
if (((required1 && b))) {
required1();
}
// error, extra parens are on purpose here
if ((required1)) {
}
// error
if (b && (required1 || required2)) {
}
// error
if ((required1 || required2) && b) {
}
// error
if (b && (required1 ?? required2)) {
}
// error
if ((required1 ?? required2) && b) {
}
}
function checksConsole() {
@ -98,6 +149,26 @@ function checksPropertyAccess() {
// error
x1.a.b.c && x2.a.b.c();
// error, extra parens are on purpose here
if ((x1.a.b.c)) {
}
// error
if (1 && (x1.a.b.c || x2.a.b.c)) {
}
// error
if ((x1.a.b.c || x2.a.b.c) && 1) {
}
// error
if (1 && (x1.a.b.c ?? x2.a.b.c)) {
}
// error
if ((x1.a.b.c ?? x2.a.b.c) && 1) {
}
}
class Foo {
@ -152,6 +223,18 @@ function test(required1, required2, b, optional) {
if (required1 && b) {
}
// error
if (required1 || b) {
}
// error
if (required1 || required2) {
}
// error
if (required1 !== null && required1 !== void 0 ? required1 : b) {
}
// error
if (required1 !== null && required1 !== void 0 ? required1 : required2) {
}
// error
if (((required1 && b))) {
}
// ok
@ -159,9 +242,36 @@ function test(required1, required2, b, optional) {
required1();
}
// ok
if (required1 || b) {
required1();
}
// ok
if (required1 !== null && required1 !== void 0 ? required1 : b) {
required1();
}
// ok
if (b !== null && b !== void 0 ? b : required1) {
required1();
}
// ok
if (((required1 && b))) {
required1();
}
// error, extra parens are on purpose here
if ((required1)) {
}
// error
if (b && (required1 || required2)) {
}
// error
if ((required1 || required2) && b) {
}
// error
if (b && (required1 !== null && required1 !== void 0 ? required1 : required2)) {
}
// error
if ((required1 !== null && required1 !== void 0 ? required1 : required2) && b) {
}
}
function checksConsole() {
// error
@ -169,6 +279,7 @@ function checksConsole() {
(window.console.firebug || (window.console.error && window.console.table));
}
function checksPropertyAccess() {
var _a, _b;
var x = {
foo: {
bar: function () { return true; }
@ -193,6 +304,21 @@ function checksPropertyAccess() {
};
// error
x1.a.b.c && x2.a.b.c();
// error, extra parens are on purpose here
if ((x1.a.b.c)) {
}
// error
if (1 && (x1.a.b.c || x2.a.b.c)) {
}
// error
if ((x1.a.b.c || x2.a.b.c) && 1) {
}
// error
if (1 && ((_a = x1.a.b.c) !== null && _a !== void 0 ? _a : x2.a.b.c)) {
}
// error
if (((_b = x1.a.b.c) !== null && _b !== void 0 ? _b : x2.a.b.c) && 1) {
}
}
var Foo = /** @class */ (function () {
function Foo() {

View File

@ -105,6 +105,30 @@ function test(required1: () => boolean, required2: () => boolean, b: boolean, op
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 8, 65))
}
// error
if (required1 || b) {
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 8, 65))
}
// error
if (required1 || required2) {
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
>required2 : Symbol(required2, Decl(truthinessCallExpressionCoercion2.ts, 8, 39))
}
// error
if (required1 ?? b) {
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 8, 65))
}
// error
if (required1 ?? required2) {
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
>required2 : Symbol(required2, Decl(truthinessCallExpressionCoercion2.ts, 8, 39))
}
// error
if (((required1 && b))) {
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
@ -120,6 +144,33 @@ function test(required1: () => boolean, required2: () => boolean, b: boolean, op
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
}
// ok
if (required1 || b) {
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 8, 65))
required1();
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
}
// ok
if (required1 ?? b) {
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 8, 65))
required1();
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
}
// ok
if (b ?? required1) {
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 8, 65))
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
required1();
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
}
// ok
if (((required1 && b))) {
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
@ -128,10 +179,43 @@ function test(required1: () => boolean, required2: () => boolean, b: boolean, op
required1();
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
}
// error, extra parens are on purpose here
if ((required1)) {
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
}
// error
if (b && (required1 || required2)) {
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 8, 65))
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
>required2 : Symbol(required2, Decl(truthinessCallExpressionCoercion2.ts, 8, 39))
}
// error
if ((required1 || required2) && b) {
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
>required2 : Symbol(required2, Decl(truthinessCallExpressionCoercion2.ts, 8, 39))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 8, 65))
}
// error
if (b && (required1 ?? required2)) {
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 8, 65))
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
>required2 : Symbol(required2, Decl(truthinessCallExpressionCoercion2.ts, 8, 39))
}
// error
if ((required1 ?? required2) && b) {
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 8, 14))
>required2 : Symbol(required2, Decl(truthinessCallExpressionCoercion2.ts, 8, 39))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 8, 65))
}
}
function checksConsole() {
>checksConsole : Symbol(checksConsole, Decl(truthinessCallExpressionCoercion2.ts, 59, 1))
>checksConsole : Symbol(checksConsole, Decl(truthinessCallExpressionCoercion2.ts, 110, 1))
// error
typeof window !== 'undefined' && window.console &&
@ -157,70 +241,70 @@ function checksConsole() {
}
function checksPropertyAccess() {
>checksPropertyAccess : Symbol(checksPropertyAccess, Decl(truthinessCallExpressionCoercion2.ts, 65, 1))
>checksPropertyAccess : Symbol(checksPropertyAccess, Decl(truthinessCallExpressionCoercion2.ts, 116, 1))
const x = {
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 68, 9))
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 119, 9))
foo: {
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 68, 15))
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 119, 15))
bar() { return true; }
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 69, 14))
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 120, 14))
}
}
// error
x.foo.bar && console.log('x.foo.bar');
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 69, 14))
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 68, 15))
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 68, 9))
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 68, 15))
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 69, 14))
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 120, 14))
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 119, 15))
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 119, 9))
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 119, 15))
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 120, 14))
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
// error
1 && x.foo.bar && console.log('x.foo.bar');
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 69, 14))
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 68, 15))
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 68, 9))
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 68, 15))
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 69, 14))
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 120, 14))
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 119, 15))
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 119, 9))
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 119, 15))
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 120, 14))
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
// ok
x.foo.bar && x.foo.bar();
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 69, 14))
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 68, 15))
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 68, 9))
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 68, 15))
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 69, 14))
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 69, 14))
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 68, 15))
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 68, 9))
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 68, 15))
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 69, 14))
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 120, 14))
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 119, 15))
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 119, 9))
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 119, 15))
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 120, 14))
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 120, 14))
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 119, 15))
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 119, 9))
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 119, 15))
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 120, 14))
// ok
x.foo.bar && 1 && x.foo.bar();
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 69, 14))
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 68, 15))
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 68, 9))
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 68, 15))
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 69, 14))
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 69, 14))
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 68, 15))
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 68, 9))
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 68, 15))
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 69, 14))
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 120, 14))
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 119, 15))
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 119, 9))
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 119, 15))
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 120, 14))
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 120, 14))
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 119, 15))
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 119, 9))
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 119, 15))
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 120, 14))
// ok
const y = A.from && (A.from as Function) !== B.from ? true : false;
>y : Symbol(y, Decl(truthinessCallExpressionCoercion2.ts, 87, 9))
>y : Symbol(y, Decl(truthinessCallExpressionCoercion2.ts, 138, 9))
>A.from : Symbol(A.from, Decl(truthinessCallExpressionCoercion2.ts, 0, 17))
>A : Symbol(A, Decl(truthinessCallExpressionCoercion2.ts, 0, 0))
>from : Symbol(A.from, Decl(truthinessCallExpressionCoercion2.ts, 0, 17))
@ -233,98 +317,181 @@ function checksPropertyAccess() {
>from : Symbol(B.from, Decl(truthinessCallExpressionCoercion2.ts, 4, 17))
y;
>y : Symbol(y, Decl(truthinessCallExpressionCoercion2.ts, 87, 9))
>y : Symbol(y, Decl(truthinessCallExpressionCoercion2.ts, 138, 9))
const x1 = {
>x1 : Symbol(x1, Decl(truthinessCallExpressionCoercion2.ts, 90, 9))
>x1 : Symbol(x1, Decl(truthinessCallExpressionCoercion2.ts, 141, 9))
a: { b: { c: () => {} } }
>a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 90, 16))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 91, 12))
>c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 91, 17))
>a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 141, 16))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 142, 12))
>c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 142, 17))
}
const x2 = {
>x2 : Symbol(x2, Decl(truthinessCallExpressionCoercion2.ts, 93, 9))
>x2 : Symbol(x2, Decl(truthinessCallExpressionCoercion2.ts, 144, 9))
a: { b: { c: () => {} } }
>a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 93, 16))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 94, 12))
>c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 94, 17))
>a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 144, 16))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 145, 12))
>c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 145, 17))
}
// error
x1.a.b.c && x2.a.b.c();
>x1.a.b.c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 91, 17))
>x1.a.b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 91, 12))
>x1.a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 90, 16))
>x1 : Symbol(x1, Decl(truthinessCallExpressionCoercion2.ts, 90, 9))
>a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 90, 16))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 91, 12))
>c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 91, 17))
>x2.a.b.c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 94, 17))
>x2.a.b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 94, 12))
>x2.a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 93, 16))
>x2 : Symbol(x2, Decl(truthinessCallExpressionCoercion2.ts, 93, 9))
>a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 93, 16))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 94, 12))
>c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 94, 17))
>x1.a.b.c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 142, 17))
>x1.a.b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 142, 12))
>x1.a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 141, 16))
>x1 : Symbol(x1, Decl(truthinessCallExpressionCoercion2.ts, 141, 9))
>a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 141, 16))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 142, 12))
>c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 142, 17))
>x2.a.b.c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 145, 17))
>x2.a.b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 145, 12))
>x2.a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 144, 16))
>x2 : Symbol(x2, Decl(truthinessCallExpressionCoercion2.ts, 144, 9))
>a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 144, 16))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 145, 12))
>c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 145, 17))
// error, extra parens are on purpose here
if ((x1.a.b.c)) {
>x1.a.b.c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 142, 17))
>x1.a.b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 142, 12))
>x1.a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 141, 16))
>x1 : Symbol(x1, Decl(truthinessCallExpressionCoercion2.ts, 141, 9))
>a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 141, 16))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 142, 12))
>c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 142, 17))
}
// error
if (1 && (x1.a.b.c || x2.a.b.c)) {
>x1.a.b.c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 142, 17))
>x1.a.b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 142, 12))
>x1.a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 141, 16))
>x1 : Symbol(x1, Decl(truthinessCallExpressionCoercion2.ts, 141, 9))
>a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 141, 16))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 142, 12))
>c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 142, 17))
>x2.a.b.c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 145, 17))
>x2.a.b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 145, 12))
>x2.a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 144, 16))
>x2 : Symbol(x2, Decl(truthinessCallExpressionCoercion2.ts, 144, 9))
>a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 144, 16))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 145, 12))
>c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 145, 17))
}
// error
if ((x1.a.b.c || x2.a.b.c) && 1) {
>x1.a.b.c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 142, 17))
>x1.a.b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 142, 12))
>x1.a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 141, 16))
>x1 : Symbol(x1, Decl(truthinessCallExpressionCoercion2.ts, 141, 9))
>a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 141, 16))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 142, 12))
>c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 142, 17))
>x2.a.b.c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 145, 17))
>x2.a.b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 145, 12))
>x2.a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 144, 16))
>x2 : Symbol(x2, Decl(truthinessCallExpressionCoercion2.ts, 144, 9))
>a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 144, 16))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 145, 12))
>c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 145, 17))
}
// error
if (1 && (x1.a.b.c ?? x2.a.b.c)) {
>x1.a.b.c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 142, 17))
>x1.a.b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 142, 12))
>x1.a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 141, 16))
>x1 : Symbol(x1, Decl(truthinessCallExpressionCoercion2.ts, 141, 9))
>a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 141, 16))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 142, 12))
>c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 142, 17))
>x2.a.b.c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 145, 17))
>x2.a.b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 145, 12))
>x2.a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 144, 16))
>x2 : Symbol(x2, Decl(truthinessCallExpressionCoercion2.ts, 144, 9))
>a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 144, 16))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 145, 12))
>c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 145, 17))
}
// error
if ((x1.a.b.c ?? x2.a.b.c) && 1) {
>x1.a.b.c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 142, 17))
>x1.a.b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 142, 12))
>x1.a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 141, 16))
>x1 : Symbol(x1, Decl(truthinessCallExpressionCoercion2.ts, 141, 9))
>a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 141, 16))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 142, 12))
>c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 142, 17))
>x2.a.b.c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 145, 17))
>x2.a.b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 145, 12))
>x2.a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 144, 16))
>x2 : Symbol(x2, Decl(truthinessCallExpressionCoercion2.ts, 144, 9))
>a : Symbol(a, Decl(truthinessCallExpressionCoercion2.ts, 144, 16))
>b : Symbol(b, Decl(truthinessCallExpressionCoercion2.ts, 145, 12))
>c : Symbol(c, Decl(truthinessCallExpressionCoercion2.ts, 145, 17))
}
}
class Foo {
>Foo : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 99, 1))
>Foo : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 170, 1))
optional?: () => boolean;
>optional : Symbol(Foo.optional, Decl(truthinessCallExpressionCoercion2.ts, 101, 11))
>optional : Symbol(Foo.optional, Decl(truthinessCallExpressionCoercion2.ts, 172, 11))
required() {
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 102, 29))
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 173, 29))
return true;
}
test() {
>test : Symbol(Foo.test, Decl(truthinessCallExpressionCoercion2.ts, 105, 5))
>test : Symbol(Foo.test, Decl(truthinessCallExpressionCoercion2.ts, 176, 5))
// error
this.required && console.log('required');
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 102, 29))
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 99, 1))
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 102, 29))
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 173, 29))
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 170, 1))
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 173, 29))
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
// error
1 && this.required && console.log('required');
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 102, 29))
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 99, 1))
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 102, 29))
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 173, 29))
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 170, 1))
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 173, 29))
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
// ok
this.required && this.required();
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 102, 29))
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 99, 1))
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 102, 29))
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 102, 29))
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 99, 1))
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 102, 29))
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 173, 29))
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 170, 1))
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 173, 29))
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 173, 29))
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 170, 1))
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 173, 29))
// ok
this.required && 1 && this.required();
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 102, 29))
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 99, 1))
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 102, 29))
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 102, 29))
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 99, 1))
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 102, 29))
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 173, 29))
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 170, 1))
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 173, 29))
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 173, 29))
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 170, 1))
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 173, 29))
// ok
1 && this.optional && console.log('optional');
>this.optional : Symbol(Foo.optional, Decl(truthinessCallExpressionCoercion2.ts, 101, 11))
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 99, 1))
>optional : Symbol(Foo.optional, Decl(truthinessCallExpressionCoercion2.ts, 101, 11))
>this.optional : Symbol(Foo.optional, Decl(truthinessCallExpressionCoercion2.ts, 172, 11))
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 170, 1))
>optional : Symbol(Foo.optional, Decl(truthinessCallExpressionCoercion2.ts, 172, 11))
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))

View File

@ -154,6 +154,34 @@ function test(required1: () => boolean, required2: () => boolean, b: boolean, op
>b : boolean
}
// error
if (required1 || b) {
>required1 || b : () => boolean
>required1 : () => boolean
>b : boolean
}
// error
if (required1 || required2) {
>required1 || required2 : () => boolean
>required1 : () => boolean
>required2 : () => boolean
}
// error
if (required1 ?? b) {
>required1 ?? b : () => boolean
>required1 : () => boolean
>b : boolean
}
// error
if (required1 ?? required2) {
>required1 ?? required2 : () => boolean
>required1 : () => boolean
>required2 : () => boolean
}
// error
if (((required1 && b))) {
>((required1 && b)) : boolean
@ -174,6 +202,39 @@ function test(required1: () => boolean, required2: () => boolean, b: boolean, op
>required1 : () => boolean
}
// ok
if (required1 || b) {
>required1 || b : () => boolean
>required1 : () => boolean
>b : boolean
required1();
>required1() : boolean
>required1 : () => boolean
}
// ok
if (required1 ?? b) {
>required1 ?? b : () => boolean
>required1 : () => boolean
>b : boolean
required1();
>required1() : boolean
>required1 : () => boolean
}
// ok
if (b ?? required1) {
>b ?? required1 : boolean
>b : boolean
>required1 : () => boolean
required1();
>required1() : boolean
>required1 : () => boolean
}
// ok
if (((required1 && b))) {
>((required1 && b)) : boolean
@ -186,6 +247,52 @@ function test(required1: () => boolean, required2: () => boolean, b: boolean, op
>required1() : boolean
>required1 : () => boolean
}
// error, extra parens are on purpose here
if ((required1)) {
>(required1) : () => boolean
>required1 : () => boolean
}
// error
if (b && (required1 || required2)) {
>b && (required1 || required2) : false | (() => boolean)
>b : boolean
>(required1 || required2) : () => boolean
>required1 || required2 : () => boolean
>required1 : () => boolean
>required2 : () => boolean
}
// error
if ((required1 || required2) && b) {
>(required1 || required2) && b : boolean
>(required1 || required2) : () => boolean
>required1 || required2 : () => boolean
>required1 : () => boolean
>required2 : () => boolean
>b : boolean
}
// error
if (b && (required1 ?? required2)) {
>b && (required1 ?? required2) : false | (() => boolean)
>b : boolean
>(required1 ?? required2) : () => boolean
>required1 ?? required2 : () => boolean
>required1 : () => boolean
>required2 : () => boolean
}
// error
if ((required1 ?? required2) && b) {
>(required1 ?? required2) && b : boolean
>(required1 ?? required2) : () => boolean
>required1 ?? required2 : () => boolean
>required1 : () => boolean
>required2 : () => boolean
>b : boolean
}
}
function checksConsole() {
@ -372,6 +479,106 @@ function checksPropertyAccess() {
>a : { b: { c: () => void; }; }
>b : { c: () => void; }
>c : () => void
// error, extra parens are on purpose here
if ((x1.a.b.c)) {
>(x1.a.b.c) : () => void
>x1.a.b.c : () => void
>x1.a.b : { c: () => void; }
>x1.a : { b: { c: () => void; }; }
>x1 : { a: { b: { c: () => void; }; }; }
>a : { b: { c: () => void; }; }
>b : { c: () => void; }
>c : () => void
}
// error
if (1 && (x1.a.b.c || x2.a.b.c)) {
>1 && (x1.a.b.c || x2.a.b.c) : () => void
>1 : 1
>(x1.a.b.c || x2.a.b.c) : () => void
>x1.a.b.c || x2.a.b.c : () => void
>x1.a.b.c : () => void
>x1.a.b : { c: () => void; }
>x1.a : { b: { c: () => void; }; }
>x1 : { a: { b: { c: () => void; }; }; }
>a : { b: { c: () => void; }; }
>b : { c: () => void; }
>c : () => void
>x2.a.b.c : () => void
>x2.a.b : { c: () => void; }
>x2.a : { b: { c: () => void; }; }
>x2 : { a: { b: { c: () => void; }; }; }
>a : { b: { c: () => void; }; }
>b : { c: () => void; }
>c : () => void
}
// error
if ((x1.a.b.c || x2.a.b.c) && 1) {
>(x1.a.b.c || x2.a.b.c) && 1 : 1
>(x1.a.b.c || x2.a.b.c) : () => void
>x1.a.b.c || x2.a.b.c : () => void
>x1.a.b.c : () => void
>x1.a.b : { c: () => void; }
>x1.a : { b: { c: () => void; }; }
>x1 : { a: { b: { c: () => void; }; }; }
>a : { b: { c: () => void; }; }
>b : { c: () => void; }
>c : () => void
>x2.a.b.c : () => void
>x2.a.b : { c: () => void; }
>x2.a : { b: { c: () => void; }; }
>x2 : { a: { b: { c: () => void; }; }; }
>a : { b: { c: () => void; }; }
>b : { c: () => void; }
>c : () => void
>1 : 1
}
// error
if (1 && (x1.a.b.c ?? x2.a.b.c)) {
>1 && (x1.a.b.c ?? x2.a.b.c) : () => void
>1 : 1
>(x1.a.b.c ?? x2.a.b.c) : () => void
>x1.a.b.c ?? x2.a.b.c : () => void
>x1.a.b.c : () => void
>x1.a.b : { c: () => void; }
>x1.a : { b: { c: () => void; }; }
>x1 : { a: { b: { c: () => void; }; }; }
>a : { b: { c: () => void; }; }
>b : { c: () => void; }
>c : () => void
>x2.a.b.c : () => void
>x2.a.b : { c: () => void; }
>x2.a : { b: { c: () => void; }; }
>x2 : { a: { b: { c: () => void; }; }; }
>a : { b: { c: () => void; }; }
>b : { c: () => void; }
>c : () => void
}
// error
if ((x1.a.b.c ?? x2.a.b.c) && 1) {
>(x1.a.b.c ?? x2.a.b.c) && 1 : 1
>(x1.a.b.c ?? x2.a.b.c) : () => void
>x1.a.b.c ?? x2.a.b.c : () => void
>x1.a.b.c : () => void
>x1.a.b : { c: () => void; }
>x1.a : { b: { c: () => void; }; }
>x1 : { a: { b: { c: () => void; }; }; }
>a : { b: { c: () => void; }; }
>b : { c: () => void; }
>c : () => void
>x2.a.b.c : () => void
>x2.a.b : { c: () => void; }
>x2.a : { b: { c: () => void; }; }
>x2 : { a: { b: { c: () => void; }; }; }
>a : { b: { c: () => void; }; }
>b : { c: () => void; }
>c : () => void
>1 : 1
}
}
class Foo {

View File

@ -1,8 +1,9 @@
tests/cases/compiler/uncalledFunctionChecksInConditional2.ts(20,5): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/uncalledFunctionChecksInConditional2.ts(38,5): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/uncalledFunctionChecksInConditional2.ts(30,7): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/uncalledFunctionChecksInConditional2.ts(49,5): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
==== tests/cases/compiler/uncalledFunctionChecksInConditional2.ts (2 errors) ====
==== tests/cases/compiler/uncalledFunctionChecksInConditional2.ts (3 errors) ====
{
const perf = window.performance
@ -28,6 +29,19 @@ tests/cases/compiler/uncalledFunctionChecksInConditional2.ts(38,5): error TS2774
) {
perf.mark("");
}
// With ??
if (
(
perf &&
perf.mark &&
perf.measure
~~~~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
) ?? !!true
) {
perf.mark("");
}
};
// Original #49192

View File

@ -22,6 +22,17 @@
) {
perf.mark("");
}
// With ??
if (
(
perf &&
perf.mark &&
perf.measure
) ?? !!true
) {
perf.mark("");
}
};
// Original #49192
@ -50,6 +61,7 @@ declare let inBrowser: boolean;
//// [uncalledFunctionChecksInConditional2.js]
var _a;
{
var perf = window.performance;
// Simplified
@ -67,6 +79,12 @@ declare let inBrowser: boolean;
perf.measure || !!true) {
perf.mark("");
}
// With ??
if ((_a = (perf &&
perf.mark &&
perf.measure)) !== null && _a !== void 0 ? _a : !!true) {
perf.mark("");
}
}
;
{

View File

@ -62,23 +62,47 @@
perf.mark("");
>perf.mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 1, 7))
>mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
}
// With ??
if (
(
perf &&
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 1, 7))
perf.mark &&
>perf.mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 1, 7))
>mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
perf.measure
>perf.measure : Symbol(Performance.measure, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 1, 7))
>measure : Symbol(Performance.measure, Decl(lib.dom.d.ts, --, --))
) ?? !!true
) {
perf.mark("");
>perf.mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 1, 7))
>mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
}
};
// Original #49192
declare let inBrowser: boolean;
>inBrowser : Symbol(inBrowser, Decl(uncalledFunctionChecksInConditional2.ts, 26, 11))
>inBrowser : Symbol(inBrowser, Decl(uncalledFunctionChecksInConditional2.ts, 37, 11))
{
let mark;
>mark : Symbol(mark, Decl(uncalledFunctionChecksInConditional2.ts, 28, 5))
>mark : Symbol(mark, Decl(uncalledFunctionChecksInConditional2.ts, 39, 5))
let measure;
>measure : Symbol(measure, Decl(uncalledFunctionChecksInConditional2.ts, 29, 5))
>measure : Symbol(measure, Decl(uncalledFunctionChecksInConditional2.ts, 40, 5))
const perf = inBrowser && window.performance
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>inBrowser : Symbol(inBrowser, Decl(uncalledFunctionChecksInConditional2.ts, 26, 11))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 41, 7))
>inBrowser : Symbol(inBrowser, Decl(uncalledFunctionChecksInConditional2.ts, 37, 11))
>window.performance : Symbol(performance, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
>performance : Symbol(performance, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
@ -86,62 +110,62 @@ declare let inBrowser: boolean;
/* istanbul ignore if */
if (
perf &&
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 41, 7))
perf.mark &&
>perf.mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 41, 7))
>mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
perf.measure &&
>perf.measure : Symbol(Performance.measure, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 41, 7))
>measure : Symbol(Performance.measure, Decl(lib.dom.d.ts, --, --))
perf.clearMarks &&
>perf.clearMarks : Symbol(Performance.clearMarks, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 41, 7))
>clearMarks : Symbol(Performance.clearMarks, Decl(lib.dom.d.ts, --, --))
perf.clearMeasures
>perf.clearMeasures : Symbol(Performance.clearMeasures, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 41, 7))
>clearMeasures : Symbol(Performance.clearMeasures, Decl(lib.dom.d.ts, --, --))
) {
mark = (tag) => perf.mark(tag)
>mark : Symbol(mark, Decl(uncalledFunctionChecksInConditional2.ts, 28, 5))
>tag : Symbol(tag, Decl(uncalledFunctionChecksInConditional2.ts, 39, 12))
>mark : Symbol(mark, Decl(uncalledFunctionChecksInConditional2.ts, 39, 5))
>tag : Symbol(tag, Decl(uncalledFunctionChecksInConditional2.ts, 50, 12))
>perf.mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 41, 7))
>mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
>tag : Symbol(tag, Decl(uncalledFunctionChecksInConditional2.ts, 39, 12))
>tag : Symbol(tag, Decl(uncalledFunctionChecksInConditional2.ts, 50, 12))
measure = (name, startTag, endTag) => {
>measure : Symbol(measure, Decl(uncalledFunctionChecksInConditional2.ts, 29, 5))
>name : Symbol(name, Decl(uncalledFunctionChecksInConditional2.ts, 40, 15))
>startTag : Symbol(startTag, Decl(uncalledFunctionChecksInConditional2.ts, 40, 20))
>endTag : Symbol(endTag, Decl(uncalledFunctionChecksInConditional2.ts, 40, 30))
>measure : Symbol(measure, Decl(uncalledFunctionChecksInConditional2.ts, 40, 5))
>name : Symbol(name, Decl(uncalledFunctionChecksInConditional2.ts, 51, 15))
>startTag : Symbol(startTag, Decl(uncalledFunctionChecksInConditional2.ts, 51, 20))
>endTag : Symbol(endTag, Decl(uncalledFunctionChecksInConditional2.ts, 51, 30))
perf.measure(name, startTag, endTag)
>perf.measure : Symbol(Performance.measure, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 41, 7))
>measure : Symbol(Performance.measure, Decl(lib.dom.d.ts, --, --))
>name : Symbol(name, Decl(uncalledFunctionChecksInConditional2.ts, 40, 15))
>startTag : Symbol(startTag, Decl(uncalledFunctionChecksInConditional2.ts, 40, 20))
>endTag : Symbol(endTag, Decl(uncalledFunctionChecksInConditional2.ts, 40, 30))
>name : Symbol(name, Decl(uncalledFunctionChecksInConditional2.ts, 51, 15))
>startTag : Symbol(startTag, Decl(uncalledFunctionChecksInConditional2.ts, 51, 20))
>endTag : Symbol(endTag, Decl(uncalledFunctionChecksInConditional2.ts, 51, 30))
perf.clearMarks(startTag)
>perf.clearMarks : Symbol(Performance.clearMarks, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 41, 7))
>clearMarks : Symbol(Performance.clearMarks, Decl(lib.dom.d.ts, --, --))
>startTag : Symbol(startTag, Decl(uncalledFunctionChecksInConditional2.ts, 40, 20))
>startTag : Symbol(startTag, Decl(uncalledFunctionChecksInConditional2.ts, 51, 20))
perf.clearMarks(endTag)
>perf.clearMarks : Symbol(Performance.clearMarks, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 41, 7))
>clearMarks : Symbol(Performance.clearMarks, Decl(lib.dom.d.ts, --, --))
>endTag : Symbol(endTag, Decl(uncalledFunctionChecksInConditional2.ts, 40, 30))
>endTag : Symbol(endTag, Decl(uncalledFunctionChecksInConditional2.ts, 51, 30))
// perf.clearMeasures(name)
}

View File

@ -79,6 +79,41 @@
>perf.mark : (markName: string, markOptions?: PerformanceMarkOptions | undefined) => PerformanceMark
>perf : Performance
>mark : (markName: string, markOptions?: PerformanceMarkOptions | undefined) => PerformanceMark
>"" : ""
}
// With ??
if (
(
>( perf && perf.mark && perf.measure ) ?? !!true : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
>( perf && perf.mark && perf.measure ) : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
perf &&
>perf && perf.mark && perf.measure : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
>perf && perf.mark : (markName: string, markOptions?: PerformanceMarkOptions | undefined) => PerformanceMark
>perf : Performance
perf.mark &&
>perf.mark : (markName: string, markOptions?: PerformanceMarkOptions | undefined) => PerformanceMark
>perf : Performance
>mark : (markName: string, markOptions?: PerformanceMarkOptions | undefined) => PerformanceMark
perf.measure
>perf.measure : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
>perf : Performance
>measure : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
) ?? !!true
>!!true : true
>!true : false
>true : true
) {
perf.mark("");
>perf.mark("") : PerformanceMark
>perf.mark : (markName: string, markOptions?: PerformanceMarkOptions | undefined) => PerformanceMark
>perf : Performance
>mark : (markName: string, markOptions?: PerformanceMarkOptions | undefined) => PerformanceMark
>"" : ""
}
};

View File

@ -47,6 +47,22 @@ function test(required1: () => boolean, required2: () => boolean, b: boolean, op
if (required1 && b) {
}
// error
if (required1 || b) {
}
// error
if (required1 || required2) {
}
// error
if (required1 ?? b) {
}
// error
if (required1 ?? required2) {
}
// error
if (((required1 && b))) {
}
@ -56,10 +72,45 @@ function test(required1: () => boolean, required2: () => boolean, b: boolean, op
required1();
}
// ok
if (required1 || b) {
required1();
}
// ok
if (required1 ?? b) {
required1();
}
// ok
if (b ?? required1) {
required1();
}
// ok
if (((required1 && b))) {
required1();
}
// error, extra parens are on purpose here
if ((required1)) {
}
// error
if (b && (required1 || required2)) {
}
// error
if ((required1 || required2) && b) {
}
// error
if (b && (required1 ?? required2)) {
}
// error
if ((required1 ?? required2) && b) {
}
}
function checksConsole() {
@ -100,6 +151,26 @@ function checksPropertyAccess() {
// error
x1.a.b.c && x2.a.b.c();
// error, extra parens are on purpose here
if ((x1.a.b.c)) {
}
// error
if (1 && (x1.a.b.c || x2.a.b.c)) {
}
// error
if ((x1.a.b.c || x2.a.b.c) && 1) {
}
// error
if (1 && (x1.a.b.c ?? x2.a.b.c)) {
}
// error
if ((x1.a.b.c ?? x2.a.b.c) && 1) {
}
}
class Foo {

View File

@ -23,6 +23,17 @@
) {
perf.mark("");
}
// With ??
if (
(
perf &&
perf.mark &&
perf.measure
) ?? !!true
) {
perf.mark("");
}
};
// Original #49192