mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-12 20:01:02 -05:00
fix narrowType check with template literals (#21024)
This commit is contained in:
committed by
Mohamed Hegazy
parent
86eab34758
commit
06c9a28b36
@@ -746,11 +746,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isNarrowingTypeofOperands(expr1: Expression, expr2: Expression) {
|
||||
return expr1.kind === SyntaxKind.TypeOfExpression && isNarrowableOperand((<TypeOfExpression>expr1).expression) && expr2.kind === SyntaxKind.StringLiteral;
|
||||
return expr1.kind === SyntaxKind.TypeOfExpression && isNarrowableOperand((<TypeOfExpression>expr1).expression) && (expr2.kind === SyntaxKind.StringLiteral || expr2.kind === SyntaxKind.NoSubstitutionTemplateLiteral);
|
||||
}
|
||||
|
||||
function isNarrowableInOperands(left: Expression, right: Expression) {
|
||||
return left.kind === SyntaxKind.StringLiteral && isNarrowingExpression(right);
|
||||
return (left.kind === SyntaxKind.StringLiteral || left.kind === SyntaxKind.NoSubstitutionTemplateLiteral) && isNarrowingExpression(right);
|
||||
}
|
||||
|
||||
function isNarrowingBinaryExpression(expr: BinaryExpression) {
|
||||
|
||||
@@ -12838,10 +12838,10 @@ namespace ts {
|
||||
const operator = expr.operatorToken.kind;
|
||||
const left = getReferenceCandidate(expr.left);
|
||||
const right = getReferenceCandidate(expr.right);
|
||||
if (left.kind === SyntaxKind.TypeOfExpression && right.kind === SyntaxKind.StringLiteral) {
|
||||
if (left.kind === SyntaxKind.TypeOfExpression && (right.kind === SyntaxKind.StringLiteral || right.kind === SyntaxKind.NoSubstitutionTemplateLiteral)) {
|
||||
return narrowTypeByTypeof(type, <TypeOfExpression>left, operator, <LiteralExpression>right, assumeTrue);
|
||||
}
|
||||
if (right.kind === SyntaxKind.TypeOfExpression && left.kind === SyntaxKind.StringLiteral) {
|
||||
if (right.kind === SyntaxKind.TypeOfExpression && (left.kind === SyntaxKind.StringLiteral || left.kind === SyntaxKind.NoSubstitutionTemplateLiteral)) {
|
||||
return narrowTypeByTypeof(type, <TypeOfExpression>right, operator, <LiteralExpression>left, assumeTrue);
|
||||
}
|
||||
if (isMatchingReference(reference, left)) {
|
||||
@@ -12864,7 +12864,7 @@ namespace ts {
|
||||
return narrowTypeByInstanceof(type, expr, assumeTrue);
|
||||
case SyntaxKind.InKeyword:
|
||||
const target = getReferenceCandidate(expr.right);
|
||||
if (expr.left.kind === SyntaxKind.StringLiteral && isMatchingReference(reference, target)) {
|
||||
if ((expr.left.kind === SyntaxKind.StringLiteral || expr.left.kind === SyntaxKind.NoSubstitutionTemplateLiteral) && isMatchingReference(reference, target)) {
|
||||
return narrowByInKeyword(type, <LiteralExpression>expr.left, assumeTrue);
|
||||
}
|
||||
break;
|
||||
|
||||
19
tests/baselines/reference/controlFlowWithTemplateLiterals.js
Normal file
19
tests/baselines/reference/controlFlowWithTemplateLiterals.js
Normal file
@@ -0,0 +1,19 @@
|
||||
//// [controlFlowWithTemplateLiterals.ts]
|
||||
declare const envVar: string | undefined;
|
||||
if (typeof envVar === `string`) {
|
||||
envVar.slice(0)
|
||||
}
|
||||
|
||||
declare const obj: {test: string} | {}
|
||||
if (`test` in obj) {
|
||||
obj.test.slice(0)
|
||||
}
|
||||
|
||||
|
||||
//// [controlFlowWithTemplateLiterals.js]
|
||||
if (typeof envVar === "string") {
|
||||
envVar.slice(0);
|
||||
}
|
||||
if ("test" in obj) {
|
||||
obj.test.slice(0);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
=== tests/cases/conformance/controlFlow/controlFlowWithTemplateLiterals.ts ===
|
||||
declare const envVar: string | undefined;
|
||||
>envVar : Symbol(envVar, Decl(controlFlowWithTemplateLiterals.ts, 0, 13))
|
||||
|
||||
if (typeof envVar === `string`) {
|
||||
>envVar : Symbol(envVar, Decl(controlFlowWithTemplateLiterals.ts, 0, 13))
|
||||
|
||||
envVar.slice(0)
|
||||
>envVar.slice : Symbol(String.slice, Decl(lib.d.ts, --, --))
|
||||
>envVar : Symbol(envVar, Decl(controlFlowWithTemplateLiterals.ts, 0, 13))
|
||||
>slice : Symbol(String.slice, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
|
||||
declare const obj: {test: string} | {}
|
||||
>obj : Symbol(obj, Decl(controlFlowWithTemplateLiterals.ts, 5, 13))
|
||||
>test : Symbol(test, Decl(controlFlowWithTemplateLiterals.ts, 5, 20))
|
||||
|
||||
if (`test` in obj) {
|
||||
>obj : Symbol(obj, Decl(controlFlowWithTemplateLiterals.ts, 5, 13))
|
||||
|
||||
obj.test.slice(0)
|
||||
>obj.test.slice : Symbol(String.slice, Decl(lib.d.ts, --, --))
|
||||
>obj.test : Symbol(test, Decl(controlFlowWithTemplateLiterals.ts, 5, 20))
|
||||
>obj : Symbol(obj, Decl(controlFlowWithTemplateLiterals.ts, 5, 13))
|
||||
>test : Symbol(test, Decl(controlFlowWithTemplateLiterals.ts, 5, 20))
|
||||
>slice : Symbol(String.slice, Decl(lib.d.ts, --, --))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
=== tests/cases/conformance/controlFlow/controlFlowWithTemplateLiterals.ts ===
|
||||
declare const envVar: string | undefined;
|
||||
>envVar : string | undefined
|
||||
|
||||
if (typeof envVar === `string`) {
|
||||
>typeof envVar === `string` : boolean
|
||||
>typeof envVar : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
>envVar : string | undefined
|
||||
>`string` : "string"
|
||||
|
||||
envVar.slice(0)
|
||||
>envVar.slice(0) : string
|
||||
>envVar.slice : (start?: number | undefined, end?: number | undefined) => string
|
||||
>envVar : string
|
||||
>slice : (start?: number | undefined, end?: number | undefined) => string
|
||||
>0 : 0
|
||||
}
|
||||
|
||||
declare const obj: {test: string} | {}
|
||||
>obj : {} | { test: string; }
|
||||
>test : string
|
||||
|
||||
if (`test` in obj) {
|
||||
>`test` in obj : boolean
|
||||
>`test` : "test"
|
||||
>obj : {} | { test: string; }
|
||||
|
||||
obj.test.slice(0)
|
||||
>obj.test.slice(0) : string
|
||||
>obj.test.slice : (start?: number | undefined, end?: number | undefined) => string
|
||||
>obj.test : string
|
||||
>obj : { test: string; }
|
||||
>test : string
|
||||
>slice : (start?: number | undefined, end?: number | undefined) => string
|
||||
>0 : 0
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// @strictNullChecks: true
|
||||
declare const envVar: string | undefined;
|
||||
if (typeof envVar === `string`) {
|
||||
envVar.slice(0)
|
||||
}
|
||||
|
||||
declare const obj: {test: string} | {}
|
||||
if (`test` in obj) {
|
||||
obj.test.slice(0)
|
||||
}
|
||||
Reference in New Issue
Block a user