Skip to content

Commit 5560e8e

Browse files
committed
Narrow by constant element access callees
1 parent 261630d commit 5560e8e

File tree

5 files changed

+150
-4
lines changed

5 files changed

+150
-4
lines changed

src/compiler/binder.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,8 +1295,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
12951295
}
12961296
}
12971297
if (
1298-
expr.expression.kind === SyntaxKind.PropertyAccessExpression &&
1299-
containsNarrowableReference((expr.expression as PropertyAccessExpression).expression)
1298+
(expr.expression.kind === SyntaxKind.PropertyAccessExpression || expr.expression.kind === SyntaxKind.ElementAccessExpression) &&
1299+
containsNarrowableReference((expr.expression as PropertyAccessExpression | ElementAccessExpression).expression)
13001300
) {
13011301
return true;
13021302
}

src/compiler/checker.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27970,8 +27970,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2797027970
}
2797127971
}
2797227972
if (
27973-
expression.expression.kind === SyntaxKind.PropertyAccessExpression &&
27974-
isOrContainsMatchingReference(reference, (expression.expression as PropertyAccessExpression).expression)
27973+
(expression.expression.kind === SyntaxKind.PropertyAccessExpression || expression.expression.kind === SyntaxKind.ElementAccessExpression && isConstantReference((expression.expression as ElementAccessExpression).argumentExpression)) &&
27974+
isOrContainsMatchingReference(reference, (expression.expression as PropertyAccessExpression | ElementAccessExpression).expression)
2797527975
) {
2797627976
return true;
2797727977
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//// [tests/cases/compiler/narrowByTypePredicateFromElementAccessExpression1.ts] ////
2+
3+
=== narrowByTypePredicateFromElementAccessExpression1.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/62247
5+
6+
const isBar = Symbol("isBar");
7+
>isBar : Symbol(isBar, Decl(narrowByTypePredicateFromElementAccessExpression1.ts, 2, 5))
8+
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
9+
10+
abstract class Foo {
11+
>Foo : Symbol(Foo, Decl(narrowByTypePredicateFromElementAccessExpression1.ts, 2, 30))
12+
13+
abstract [isBar](): this is Bar;
14+
>[isBar] : Symbol(Foo[isBar], Decl(narrowByTypePredicateFromElementAccessExpression1.ts, 4, 20))
15+
>isBar : Symbol(isBar, Decl(narrowByTypePredicateFromElementAccessExpression1.ts, 2, 5))
16+
>Bar : Symbol(Bar, Decl(narrowByTypePredicateFromElementAccessExpression1.ts, 12, 1))
17+
18+
method(): void {
19+
>method : Symbol(Foo.method, Decl(narrowByTypePredicateFromElementAccessExpression1.ts, 5, 34))
20+
21+
if (this[isBar]()) {
22+
>this : Symbol(Foo, Decl(narrowByTypePredicateFromElementAccessExpression1.ts, 2, 30))
23+
>isBar : Symbol(isBar, Decl(narrowByTypePredicateFromElementAccessExpression1.ts, 2, 5))
24+
25+
this.barMethod(); // ok
26+
>this.barMethod : Symbol(Bar.barMethod, Decl(narrowByTypePredicateFromElementAccessExpression1.ts, 17, 3))
27+
>barMethod : Symbol(Bar.barMethod, Decl(narrowByTypePredicateFromElementAccessExpression1.ts, 17, 3))
28+
}
29+
}
30+
}
31+
32+
class Bar extends Foo {
33+
>Bar : Symbol(Bar, Decl(narrowByTypePredicateFromElementAccessExpression1.ts, 12, 1))
34+
>Foo : Symbol(Foo, Decl(narrowByTypePredicateFromElementAccessExpression1.ts, 2, 30))
35+
36+
override [isBar](): this is Bar {
37+
>[isBar] : Symbol(Bar[isBar], Decl(narrowByTypePredicateFromElementAccessExpression1.ts, 14, 23))
38+
>isBar : Symbol(isBar, Decl(narrowByTypePredicateFromElementAccessExpression1.ts, 2, 5))
39+
>Bar : Symbol(Bar, Decl(narrowByTypePredicateFromElementAccessExpression1.ts, 12, 1))
40+
41+
return true;
42+
}
43+
44+
barMethod(): void {}
45+
>barMethod : Symbol(Bar.barMethod, Decl(narrowByTypePredicateFromElementAccessExpression1.ts, 17, 3))
46+
}
47+
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//// [tests/cases/compiler/narrowByTypePredicateFromElementAccessExpression1.ts] ////
2+
3+
=== narrowByTypePredicateFromElementAccessExpression1.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/62247
5+
6+
const isBar = Symbol("isBar");
7+
>isBar : unique symbol
8+
> : ^^^^^^^^^^^^^
9+
>Symbol("isBar") : unique symbol
10+
> : ^^^^^^^^^^^^^
11+
>Symbol : SymbolConstructor
12+
> : ^^^^^^^^^^^^^^^^^
13+
>"isBar" : "isBar"
14+
> : ^^^^^^^
15+
16+
abstract class Foo {
17+
>Foo : Foo
18+
> : ^^^
19+
20+
abstract [isBar](): this is Bar;
21+
>[isBar] : () => this is Bar
22+
> : ^^^^^^
23+
>isBar : unique symbol
24+
> : ^^^^^^^^^^^^^
25+
26+
method(): void {
27+
>method : () => void
28+
> : ^^^^^^
29+
30+
if (this[isBar]()) {
31+
>this[isBar]() : boolean
32+
> : ^^^^^^^
33+
>this[isBar] : () => this is Bar
34+
> : ^^^^^^
35+
>this : this
36+
> : ^^^^
37+
>isBar : unique symbol
38+
> : ^^^^^^^^^^^^^
39+
40+
this.barMethod(); // ok
41+
>this.barMethod() : void
42+
> : ^^^^
43+
>this.barMethod : () => void
44+
> : ^^^^^^
45+
>this : this & Bar
46+
> : ^^^^^^^^^^
47+
>barMethod : () => void
48+
> : ^^^^^^
49+
}
50+
}
51+
}
52+
53+
class Bar extends Foo {
54+
>Bar : Bar
55+
> : ^^^
56+
>Foo : Foo
57+
> : ^^^
58+
59+
override [isBar](): this is Bar {
60+
>[isBar] : () => this is Bar
61+
> : ^^^^^^
62+
>isBar : unique symbol
63+
> : ^^^^^^^^^^^^^
64+
65+
return true;
66+
>true : true
67+
> : ^^^^
68+
}
69+
70+
barMethod(): void {}
71+
>barMethod : () => void
72+
> : ^^^^^^
73+
}
74+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// @strict: true
2+
// @target: esnext
3+
// @noEmit: true
4+
5+
// https://github.com/microsoft/TypeScript/issues/62247
6+
7+
const isBar = Symbol("isBar");
8+
9+
abstract class Foo {
10+
abstract [isBar](): this is Bar;
11+
12+
method(): void {
13+
if (this[isBar]()) {
14+
this.barMethod(); // ok
15+
}
16+
}
17+
}
18+
19+
class Bar extends Foo {
20+
override [isBar](): this is Bar {
21+
return true;
22+
}
23+
24+
barMethod(): void {}
25+
}

0 commit comments

Comments
 (0)