mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Do not reset control flow analysis on index signatures (#48427)
* do not flag index signatures as a control flow container * add tests and baselines
This commit is contained in:
parent
b975dfa102
commit
b18141b0bc
@ -1818,6 +1818,7 @@ namespace ts {
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
case SyntaxKind.MappedType:
|
||||
case SyntaxKind.IndexSignature:
|
||||
return ContainerFlags.IsContainer | ContainerFlags.HasLocals;
|
||||
|
||||
case SyntaxKind.SourceFile:
|
||||
@ -1838,7 +1839,6 @@ namespace ts {
|
||||
case SyntaxKind.JSDocFunctionType:
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
case SyntaxKind.IndexSignature:
|
||||
case SyntaxKind.ConstructorType:
|
||||
case SyntaxKind.ClassStaticBlockDeclaration:
|
||||
return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike;
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
tests/cases/compiler/controlFlowForIndexSignatures.ts(20,23): error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/controlFlowForIndexSignatures.ts (1 errors) ====
|
||||
type Foo = { bar: string };
|
||||
const boo: Foo = { bar: 'bar' };
|
||||
|
||||
function a(aboo1?: Foo) {
|
||||
if (!aboo1) return;
|
||||
const aboo2: { [key: string]: typeof aboo1.bar } = boo;
|
||||
}
|
||||
|
||||
declare let b: Foo | undefined;
|
||||
if (b) {
|
||||
const bboo: { [key: string]: typeof b.bar } = boo;
|
||||
}
|
||||
b = boo;
|
||||
const bboo: { [key: string]: typeof b.bar } = boo;
|
||||
|
||||
declare let c: string | number;
|
||||
if (typeof c === 'string') {
|
||||
type C = { [key: string]: typeof c };
|
||||
const boo1: C = { bar: 'works' };
|
||||
const boo2: C = { bar: 1 }; // should error
|
||||
~~~
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
!!! related TS6501 tests/cases/compiler/controlFlowForIndexSignatures.ts:18:16: The expected type comes from this index signature.
|
||||
}
|
||||
|
||||
40
tests/baselines/reference/controlFlowForIndexSignatures.js
Normal file
40
tests/baselines/reference/controlFlowForIndexSignatures.js
Normal file
@ -0,0 +1,40 @@
|
||||
//// [controlFlowForIndexSignatures.ts]
|
||||
type Foo = { bar: string };
|
||||
const boo: Foo = { bar: 'bar' };
|
||||
|
||||
function a(aboo1?: Foo) {
|
||||
if (!aboo1) return;
|
||||
const aboo2: { [key: string]: typeof aboo1.bar } = boo;
|
||||
}
|
||||
|
||||
declare let b: Foo | undefined;
|
||||
if (b) {
|
||||
const bboo: { [key: string]: typeof b.bar } = boo;
|
||||
}
|
||||
b = boo;
|
||||
const bboo: { [key: string]: typeof b.bar } = boo;
|
||||
|
||||
declare let c: string | number;
|
||||
if (typeof c === 'string') {
|
||||
type C = { [key: string]: typeof c };
|
||||
const boo1: C = { bar: 'works' };
|
||||
const boo2: C = { bar: 1 }; // should error
|
||||
}
|
||||
|
||||
|
||||
//// [controlFlowForIndexSignatures.js]
|
||||
var boo = { bar: 'bar' };
|
||||
function a(aboo1) {
|
||||
if (!aboo1)
|
||||
return;
|
||||
var aboo2 = boo;
|
||||
}
|
||||
if (b) {
|
||||
var bboo_1 = boo;
|
||||
}
|
||||
b = boo;
|
||||
var bboo = boo;
|
||||
if (typeof c === 'string') {
|
||||
var boo1 = { bar: 'works' };
|
||||
var boo2 = { bar: 1 }; // should error
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
=== tests/cases/compiler/controlFlowForIndexSignatures.ts ===
|
||||
type Foo = { bar: string };
|
||||
>Foo : Symbol(Foo, Decl(controlFlowForIndexSignatures.ts, 0, 0))
|
||||
>bar : Symbol(bar, Decl(controlFlowForIndexSignatures.ts, 0, 12))
|
||||
|
||||
const boo: Foo = { bar: 'bar' };
|
||||
>boo : Symbol(boo, Decl(controlFlowForIndexSignatures.ts, 1, 5))
|
||||
>Foo : Symbol(Foo, Decl(controlFlowForIndexSignatures.ts, 0, 0))
|
||||
>bar : Symbol(bar, Decl(controlFlowForIndexSignatures.ts, 1, 18))
|
||||
|
||||
function a(aboo1?: Foo) {
|
||||
>a : Symbol(a, Decl(controlFlowForIndexSignatures.ts, 1, 32))
|
||||
>aboo1 : Symbol(aboo1, Decl(controlFlowForIndexSignatures.ts, 3, 11))
|
||||
>Foo : Symbol(Foo, Decl(controlFlowForIndexSignatures.ts, 0, 0))
|
||||
|
||||
if (!aboo1) return;
|
||||
>aboo1 : Symbol(aboo1, Decl(controlFlowForIndexSignatures.ts, 3, 11))
|
||||
|
||||
const aboo2: { [key: string]: typeof aboo1.bar } = boo;
|
||||
>aboo2 : Symbol(aboo2, Decl(controlFlowForIndexSignatures.ts, 5, 9))
|
||||
>key : Symbol(key, Decl(controlFlowForIndexSignatures.ts, 5, 20))
|
||||
>aboo1.bar : Symbol(bar, Decl(controlFlowForIndexSignatures.ts, 0, 12))
|
||||
>aboo1 : Symbol(aboo1, Decl(controlFlowForIndexSignatures.ts, 3, 11))
|
||||
>bar : Symbol(bar, Decl(controlFlowForIndexSignatures.ts, 0, 12))
|
||||
>boo : Symbol(boo, Decl(controlFlowForIndexSignatures.ts, 1, 5))
|
||||
}
|
||||
|
||||
declare let b: Foo | undefined;
|
||||
>b : Symbol(b, Decl(controlFlowForIndexSignatures.ts, 8, 11))
|
||||
>Foo : Symbol(Foo, Decl(controlFlowForIndexSignatures.ts, 0, 0))
|
||||
|
||||
if (b) {
|
||||
>b : Symbol(b, Decl(controlFlowForIndexSignatures.ts, 8, 11))
|
||||
|
||||
const bboo: { [key: string]: typeof b.bar } = boo;
|
||||
>bboo : Symbol(bboo, Decl(controlFlowForIndexSignatures.ts, 10, 9))
|
||||
>key : Symbol(key, Decl(controlFlowForIndexSignatures.ts, 10, 19))
|
||||
>b.bar : Symbol(bar, Decl(controlFlowForIndexSignatures.ts, 0, 12))
|
||||
>b : Symbol(b, Decl(controlFlowForIndexSignatures.ts, 8, 11))
|
||||
>bar : Symbol(bar, Decl(controlFlowForIndexSignatures.ts, 0, 12))
|
||||
>boo : Symbol(boo, Decl(controlFlowForIndexSignatures.ts, 1, 5))
|
||||
}
|
||||
b = boo;
|
||||
>b : Symbol(b, Decl(controlFlowForIndexSignatures.ts, 8, 11))
|
||||
>boo : Symbol(boo, Decl(controlFlowForIndexSignatures.ts, 1, 5))
|
||||
|
||||
const bboo: { [key: string]: typeof b.bar } = boo;
|
||||
>bboo : Symbol(bboo, Decl(controlFlowForIndexSignatures.ts, 13, 5))
|
||||
>key : Symbol(key, Decl(controlFlowForIndexSignatures.ts, 13, 15))
|
||||
>b.bar : Symbol(bar, Decl(controlFlowForIndexSignatures.ts, 0, 12))
|
||||
>b : Symbol(b, Decl(controlFlowForIndexSignatures.ts, 8, 11))
|
||||
>bar : Symbol(bar, Decl(controlFlowForIndexSignatures.ts, 0, 12))
|
||||
>boo : Symbol(boo, Decl(controlFlowForIndexSignatures.ts, 1, 5))
|
||||
|
||||
declare let c: string | number;
|
||||
>c : Symbol(c, Decl(controlFlowForIndexSignatures.ts, 15, 11))
|
||||
|
||||
if (typeof c === 'string') {
|
||||
>c : Symbol(c, Decl(controlFlowForIndexSignatures.ts, 15, 11))
|
||||
|
||||
type C = { [key: string]: typeof c };
|
||||
>C : Symbol(C, Decl(controlFlowForIndexSignatures.ts, 16, 28))
|
||||
>key : Symbol(key, Decl(controlFlowForIndexSignatures.ts, 17, 16))
|
||||
>c : Symbol(c, Decl(controlFlowForIndexSignatures.ts, 15, 11))
|
||||
|
||||
const boo1: C = { bar: 'works' };
|
||||
>boo1 : Symbol(boo1, Decl(controlFlowForIndexSignatures.ts, 18, 9))
|
||||
>C : Symbol(C, Decl(controlFlowForIndexSignatures.ts, 16, 28))
|
||||
>bar : Symbol(bar, Decl(controlFlowForIndexSignatures.ts, 18, 21))
|
||||
|
||||
const boo2: C = { bar: 1 }; // should error
|
||||
>boo2 : Symbol(boo2, Decl(controlFlowForIndexSignatures.ts, 19, 9))
|
||||
>C : Symbol(C, Decl(controlFlowForIndexSignatures.ts, 16, 28))
|
||||
>bar : Symbol(bar, Decl(controlFlowForIndexSignatures.ts, 19, 21))
|
||||
}
|
||||
|
||||
@ -0,0 +1,82 @@
|
||||
=== tests/cases/compiler/controlFlowForIndexSignatures.ts ===
|
||||
type Foo = { bar: string };
|
||||
>Foo : Foo
|
||||
>bar : string
|
||||
|
||||
const boo: Foo = { bar: 'bar' };
|
||||
>boo : Foo
|
||||
>{ bar: 'bar' } : { bar: string; }
|
||||
>bar : string
|
||||
>'bar' : "bar"
|
||||
|
||||
function a(aboo1?: Foo) {
|
||||
>a : (aboo1?: Foo | undefined) => void
|
||||
>aboo1 : Foo | undefined
|
||||
|
||||
if (!aboo1) return;
|
||||
>!aboo1 : boolean
|
||||
>aboo1 : Foo | undefined
|
||||
|
||||
const aboo2: { [key: string]: typeof aboo1.bar } = boo;
|
||||
>aboo2 : { [key: string]: string; }
|
||||
>key : string
|
||||
>aboo1.bar : string
|
||||
>aboo1 : Foo
|
||||
>bar : string
|
||||
>boo : Foo
|
||||
}
|
||||
|
||||
declare let b: Foo | undefined;
|
||||
>b : Foo | undefined
|
||||
|
||||
if (b) {
|
||||
>b : Foo | undefined
|
||||
|
||||
const bboo: { [key: string]: typeof b.bar } = boo;
|
||||
>bboo : { [key: string]: string; }
|
||||
>key : string
|
||||
>b.bar : string
|
||||
>b : Foo
|
||||
>bar : string
|
||||
>boo : Foo
|
||||
}
|
||||
b = boo;
|
||||
>b = boo : Foo
|
||||
>b : Foo | undefined
|
||||
>boo : Foo
|
||||
|
||||
const bboo: { [key: string]: typeof b.bar } = boo;
|
||||
>bboo : { [key: string]: string; }
|
||||
>key : string
|
||||
>b.bar : string
|
||||
>b : Foo
|
||||
>bar : string
|
||||
>boo : Foo
|
||||
|
||||
declare let c: string | number;
|
||||
>c : string | number
|
||||
|
||||
if (typeof c === 'string') {
|
||||
>typeof c === 'string' : boolean
|
||||
>typeof c : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
>c : string | number
|
||||
>'string' : "string"
|
||||
|
||||
type C = { [key: string]: typeof c };
|
||||
>C : { [key: string]: string; }
|
||||
>key : string
|
||||
>c : string
|
||||
|
||||
const boo1: C = { bar: 'works' };
|
||||
>boo1 : { [key: string]: string; }
|
||||
>{ bar: 'works' } : { bar: string; }
|
||||
>bar : string
|
||||
>'works' : "works"
|
||||
|
||||
const boo2: C = { bar: 1 }; // should error
|
||||
>boo2 : { [key: string]: string; }
|
||||
>{ bar: 1 } : { bar: number; }
|
||||
>bar : number
|
||||
>1 : 1
|
||||
}
|
||||
|
||||
23
tests/cases/compiler/controlFlowForIndexSignatures.ts
Normal file
23
tests/cases/compiler/controlFlowForIndexSignatures.ts
Normal file
@ -0,0 +1,23 @@
|
||||
// @strictNullChecks: true
|
||||
|
||||
type Foo = { bar: string };
|
||||
const boo: Foo = { bar: 'bar' };
|
||||
|
||||
function a(aboo1?: Foo) {
|
||||
if (!aboo1) return;
|
||||
const aboo2: { [key: string]: typeof aboo1.bar } = boo;
|
||||
}
|
||||
|
||||
declare let b: Foo | undefined;
|
||||
if (b) {
|
||||
const bboo: { [key: string]: typeof b.bar } = boo;
|
||||
}
|
||||
b = boo;
|
||||
const bboo: { [key: string]: typeof b.bar } = boo;
|
||||
|
||||
declare let c: string | number;
|
||||
if (typeof c === 'string') {
|
||||
type C = { [key: string]: typeof c };
|
||||
const boo1: C = { bar: 'works' };
|
||||
const boo2: C = { bar: 1 }; // should error
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user