Avoid incorrect narrowings using const variables from binding elemens with literal initializers (#56347)

This commit is contained in:
Mateusz Burzyński 2023-11-21 21:24:02 +01:00 committed by GitHub
parent d845ee2b6a
commit 2c0c128e98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 66 additions and 1 deletions

View File

@ -26214,7 +26214,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (hasOnlyExpressionInitializer(declaration) && isBlockScopedNameDeclaredBeforeUse(declaration, node)) {
const initializer = getEffectiveInitializer(declaration);
if (initializer) {
return tryGetNameFromType(getTypeOfExpression(initializer));
const initializerType = isBindingPattern(declaration.parent) ? getTypeForBindingElement(declaration as BindingElement) : getTypeOfExpression(initializer);
return initializerType && tryGetNameFromType(initializerType);
}
if (isEnumMember(declaration)) {
return getTextOfPropertyName(declaration.name);

View File

@ -0,0 +1,24 @@
//// [tests/cases/compiler/avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts] ////
=== avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts ===
declare const foo: ["a", string, number] | ["b", string, boolean];
>foo : Symbol(foo, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 0, 13))
export function test(arg: { index?: number }) {
>test : Symbol(test, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 0, 66))
>arg : Symbol(arg, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 2, 21))
>index : Symbol(index, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 2, 27))
const { index = 0 } = arg;
>index : Symbol(index, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 3, 9))
>arg : Symbol(arg, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 2, 21))
if (foo[index] === "a") {
>foo : Symbol(foo, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 0, 13))
>index : Symbol(index, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 3, 9))
foo;
>foo : Symbol(foo, Decl(avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts, 0, 13))
}
}

View File

@ -0,0 +1,28 @@
//// [tests/cases/compiler/avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts] ////
=== avoidNarrowingUsingConstVariableFromBindingElementWithLiteralInitializer.ts ===
declare const foo: ["a", string, number] | ["b", string, boolean];
>foo : ["a", string, number] | ["b", string, boolean]
export function test(arg: { index?: number }) {
>test : (arg: { index?: number | undefined; }) => void
>arg : { index?: number | undefined; }
>index : number | undefined
const { index = 0 } = arg;
>index : number
>0 : 0
>arg : { index?: number | undefined; }
if (foo[index] === "a") {
>foo[index] === "a" : boolean
>foo[index] : string | number | boolean
>foo : ["a", string, number] | ["b", string, boolean]
>index : number
>"a" : "a"
foo;
>foo : ["a", string, number] | ["b", string, boolean]
}
}

View File

@ -0,0 +1,12 @@
// @strict: true
// @noEmit: true
declare const foo: ["a", string, number] | ["b", string, boolean];
export function test(arg: { index?: number }) {
const { index = 0 } = arg;
if (foo[index] === "a") {
foo;
}
}