Skip to content

Commit 9b9f3f2

Browse files
committed
Merge branch 'master' into definiteAssignmentAssertions
2 parents 02fd11e + e684f30 commit 9b9f3f2

File tree

5 files changed

+296
-0
lines changed

5 files changed

+296
-0
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8869,13 +8869,15 @@ namespace ts {
88698869
// An object type S is considered to be derived from an object type T if
88708870
// S is a union type and every constituent of S is derived from T,
88718871
// T is a union type and S is derived from at least one constituent of T, or
8872+
// S is a type variable with a base constraint that is derived from T,
88728873
// T is one of the global types Object and Function and S is a subtype of T, or
88738874
// T occurs directly or indirectly in an 'extends' clause of S.
88748875
// Note that this check ignores type parameters and only considers the
88758876
// inheritance hierarchy.
88768877
function isTypeDerivedFrom(source: Type, target: Type): boolean {
88778878
return source.flags & TypeFlags.Union ? every((<UnionType>source).types, t => isTypeDerivedFrom(t, target)) :
88788879
target.flags & TypeFlags.Union ? some((<UnionType>target).types, t => isTypeDerivedFrom(source, t)) :
8880+
source.flags & TypeFlags.TypeVariable ? isTypeDerivedFrom(getBaseConstraintOfType(source) || emptyObjectType, target) :
88798881
target === globalObjectType || target === globalFunctionType ? isTypeSubtypeOf(source, target) :
88808882
hasBaseType(source, getTargetType(target));
88818883
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
//// [narrowingConstrainedTypeVariable.ts]
2+
// Repro from #20138
3+
4+
class C { }
5+
6+
function f1<T extends C>(v: T | string): void {
7+
if (v instanceof C) {
8+
const x: T = v;
9+
}
10+
else {
11+
const s: string = v;
12+
}
13+
}
14+
15+
class D { }
16+
17+
function f2<T extends C, U extends D>(v: T | U) {
18+
if (v instanceof C) {
19+
const x: T = v;
20+
}
21+
else {
22+
const y: U = v;
23+
}
24+
}
25+
26+
class E { x: string | undefined }
27+
28+
function f3<T extends E>(v: T | { x: string }) {
29+
if (v instanceof E) {
30+
const x: T = v;
31+
}
32+
else {
33+
const y: { x: string } = v;
34+
}
35+
}
36+
37+
38+
//// [narrowingConstrainedTypeVariable.js]
39+
"use strict";
40+
// Repro from #20138
41+
var C = /** @class */ (function () {
42+
function C() {
43+
}
44+
return C;
45+
}());
46+
function f1(v) {
47+
if (v instanceof C) {
48+
var x = v;
49+
}
50+
else {
51+
var s = v;
52+
}
53+
}
54+
var D = /** @class */ (function () {
55+
function D() {
56+
}
57+
return D;
58+
}());
59+
function f2(v) {
60+
if (v instanceof C) {
61+
var x = v;
62+
}
63+
else {
64+
var y = v;
65+
}
66+
}
67+
var E = /** @class */ (function () {
68+
function E() {
69+
}
70+
return E;
71+
}());
72+
function f3(v) {
73+
if (v instanceof E) {
74+
var x = v;
75+
}
76+
else {
77+
var y = v;
78+
}
79+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
=== tests/cases/conformance/types/typeRelationships/instanceOf/narrowingConstrainedTypeVariable.ts ===
2+
// Repro from #20138
3+
4+
class C { }
5+
>C : Symbol(C, Decl(narrowingConstrainedTypeVariable.ts, 0, 0))
6+
7+
function f1<T extends C>(v: T | string): void {
8+
>f1 : Symbol(f1, Decl(narrowingConstrainedTypeVariable.ts, 2, 11))
9+
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 4, 12))
10+
>C : Symbol(C, Decl(narrowingConstrainedTypeVariable.ts, 0, 0))
11+
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 4, 25))
12+
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 4, 12))
13+
14+
if (v instanceof C) {
15+
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 4, 25))
16+
>C : Symbol(C, Decl(narrowingConstrainedTypeVariable.ts, 0, 0))
17+
18+
const x: T = v;
19+
>x : Symbol(x, Decl(narrowingConstrainedTypeVariable.ts, 6, 13))
20+
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 4, 12))
21+
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 4, 25))
22+
}
23+
else {
24+
const s: string = v;
25+
>s : Symbol(s, Decl(narrowingConstrainedTypeVariable.ts, 9, 13))
26+
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 4, 25))
27+
}
28+
}
29+
30+
class D { }
31+
>D : Symbol(D, Decl(narrowingConstrainedTypeVariable.ts, 11, 1))
32+
33+
function f2<T extends C, U extends D>(v: T | U) {
34+
>f2 : Symbol(f2, Decl(narrowingConstrainedTypeVariable.ts, 13, 11))
35+
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 15, 12))
36+
>C : Symbol(C, Decl(narrowingConstrainedTypeVariable.ts, 0, 0))
37+
>U : Symbol(U, Decl(narrowingConstrainedTypeVariable.ts, 15, 24))
38+
>D : Symbol(D, Decl(narrowingConstrainedTypeVariable.ts, 11, 1))
39+
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 15, 38))
40+
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 15, 12))
41+
>U : Symbol(U, Decl(narrowingConstrainedTypeVariable.ts, 15, 24))
42+
43+
if (v instanceof C) {
44+
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 15, 38))
45+
>C : Symbol(C, Decl(narrowingConstrainedTypeVariable.ts, 0, 0))
46+
47+
const x: T = v;
48+
>x : Symbol(x, Decl(narrowingConstrainedTypeVariable.ts, 17, 13))
49+
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 15, 12))
50+
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 15, 38))
51+
}
52+
else {
53+
const y: U = v;
54+
>y : Symbol(y, Decl(narrowingConstrainedTypeVariable.ts, 20, 13))
55+
>U : Symbol(U, Decl(narrowingConstrainedTypeVariable.ts, 15, 24))
56+
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 15, 38))
57+
}
58+
}
59+
60+
class E { x: string | undefined }
61+
>E : Symbol(E, Decl(narrowingConstrainedTypeVariable.ts, 22, 1))
62+
>x : Symbol(E.x, Decl(narrowingConstrainedTypeVariable.ts, 24, 9))
63+
64+
function f3<T extends E>(v: T | { x: string }) {
65+
>f3 : Symbol(f3, Decl(narrowingConstrainedTypeVariable.ts, 24, 33))
66+
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 26, 12))
67+
>E : Symbol(E, Decl(narrowingConstrainedTypeVariable.ts, 22, 1))
68+
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 26, 25))
69+
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 26, 12))
70+
>x : Symbol(x, Decl(narrowingConstrainedTypeVariable.ts, 26, 33))
71+
72+
if (v instanceof E) {
73+
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 26, 25))
74+
>E : Symbol(E, Decl(narrowingConstrainedTypeVariable.ts, 22, 1))
75+
76+
const x: T = v;
77+
>x : Symbol(x, Decl(narrowingConstrainedTypeVariable.ts, 28, 13))
78+
>T : Symbol(T, Decl(narrowingConstrainedTypeVariable.ts, 26, 12))
79+
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 26, 25))
80+
}
81+
else {
82+
const y: { x: string } = v;
83+
>y : Symbol(y, Decl(narrowingConstrainedTypeVariable.ts, 31, 13))
84+
>x : Symbol(x, Decl(narrowingConstrainedTypeVariable.ts, 31, 18))
85+
>v : Symbol(v, Decl(narrowingConstrainedTypeVariable.ts, 26, 25))
86+
}
87+
}
88+
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
=== tests/cases/conformance/types/typeRelationships/instanceOf/narrowingConstrainedTypeVariable.ts ===
2+
// Repro from #20138
3+
4+
class C { }
5+
>C : C
6+
7+
function f1<T extends C>(v: T | string): void {
8+
>f1 : <T extends C>(v: string | T) => void
9+
>T : T
10+
>C : C
11+
>v : string | T
12+
>T : T
13+
14+
if (v instanceof C) {
15+
>v instanceof C : boolean
16+
>v : string | T
17+
>C : typeof C
18+
19+
const x: T = v;
20+
>x : T
21+
>T : T
22+
>v : T
23+
}
24+
else {
25+
const s: string = v;
26+
>s : string
27+
>v : string
28+
}
29+
}
30+
31+
class D { }
32+
>D : D
33+
34+
function f2<T extends C, U extends D>(v: T | U) {
35+
>f2 : <T extends C, U extends D>(v: T | U) => void
36+
>T : T
37+
>C : C
38+
>U : U
39+
>D : D
40+
>v : T | U
41+
>T : T
42+
>U : U
43+
44+
if (v instanceof C) {
45+
>v instanceof C : boolean
46+
>v : T | U
47+
>C : typeof C
48+
49+
const x: T = v;
50+
>x : T
51+
>T : T
52+
>v : T
53+
}
54+
else {
55+
const y: U = v;
56+
>y : U
57+
>U : U
58+
>v : U
59+
}
60+
}
61+
62+
class E { x: string | undefined }
63+
>E : E
64+
>x : string | undefined
65+
66+
function f3<T extends E>(v: T | { x: string }) {
67+
>f3 : <T extends E>(v: T | { x: string; }) => void
68+
>T : T
69+
>E : E
70+
>v : T | { x: string; }
71+
>T : T
72+
>x : string
73+
74+
if (v instanceof E) {
75+
>v instanceof E : boolean
76+
>v : T | { x: string; }
77+
>E : typeof E
78+
79+
const x: T = v;
80+
>x : T
81+
>T : T
82+
>v : T
83+
}
84+
else {
85+
const y: { x: string } = v;
86+
>y : { x: string; }
87+
>x : string
88+
>v : { x: string; }
89+
}
90+
}
91+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// @strict: true
2+
3+
// Repro from #20138
4+
5+
class C { }
6+
7+
function f1<T extends C>(v: T | string): void {
8+
if (v instanceof C) {
9+
const x: T = v;
10+
}
11+
else {
12+
const s: string = v;
13+
}
14+
}
15+
16+
class D { }
17+
18+
function f2<T extends C, U extends D>(v: T | U) {
19+
if (v instanceof C) {
20+
const x: T = v;
21+
}
22+
else {
23+
const y: U = v;
24+
}
25+
}
26+
27+
class E { x: string | undefined }
28+
29+
function f3<T extends E>(v: T | { x: string }) {
30+
if (v instanceof E) {
31+
const x: T = v;
32+
}
33+
else {
34+
const y: { x: string } = v;
35+
}
36+
}

0 commit comments

Comments
 (0)