Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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;
Expand Down
29 changes: 29 additions & 0 deletions tests/baselines/reference/controlFlowForIndexSignatures.errors.txt
Original file line number Diff line number Diff line change
@@ -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 changes: 40 additions & 0 deletions tests/baselines/reference/controlFlowForIndexSignatures.js
Original file line number Diff line number Diff line change
@@ -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
}
76 changes: 76 additions & 0 deletions tests/baselines/reference/controlFlowForIndexSignatures.symbols
Original file line number Diff line number Diff line change
@@ -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))
}

82 changes: 82 additions & 0 deletions tests/baselines/reference/controlFlowForIndexSignatures.types
Original file line number Diff line number Diff line change
@@ -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 changes: 23 additions & 0 deletions tests/cases/compiler/controlFlowForIndexSignatures.ts
Original file line number Diff line number Diff line change
@@ -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
}