Skip to content

Commit 4a6888a

Browse files
authored
There exist type parameters with symbols but without TypeParameterDeclaration nodes (microsoft#23690)
* There exist type parameters with symbols but without TypeParameterDeclaration nodes * Add test
1 parent 4dc4b8d commit 4a6888a

File tree

5 files changed

+229
-1
lines changed

5 files changed

+229
-1
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7296,7 +7296,8 @@ namespace ts {
72967296
}
72977297

72987298
function getConstraintDeclaration(type: TypeParameter) {
7299-
return type.symbol && getDeclarationOfKind<TypeParameterDeclaration>(type.symbol, SyntaxKind.TypeParameter).constraint;
7299+
const decl = type.symbol && getDeclarationOfKind<TypeParameterDeclaration>(type.symbol, SyntaxKind.TypeParameter);
7300+
return decl && decl.constraint;
73007301
}
73017302

73027303
function getInferredTypeParameterConstraint(typeParameter: TypeParameter) {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//// [noCrashOnThisTypeUsage.ts]
2+
interface IListenable {
3+
changeListeners: Function[] | null
4+
observe(handler: (change: any, oldValue?: any) => void, fireImmediately?: boolean): void
5+
}
6+
7+
function notifyListeners<T>(listenable: IListenable, change: T) {
8+
}
9+
10+
export class ObservableValue<T> {
11+
constructor(
12+
public value: T
13+
) {
14+
const newValue: T = value;
15+
const oldValue: any = null;
16+
notifyListeners(this, {
17+
type: "update",
18+
object: this,
19+
newValue,
20+
oldValue
21+
});
22+
}
23+
changeListeners: Function[] | null = [];
24+
observe(handler: (change: any, oldValue?: any) => void, fireImmediately?: boolean) {}
25+
}
26+
27+
//// [noCrashOnThisTypeUsage.js]
28+
"use strict";
29+
exports.__esModule = true;
30+
function notifyListeners(listenable, change) {
31+
}
32+
var ObservableValue = /** @class */ (function () {
33+
function ObservableValue(value) {
34+
this.value = value;
35+
this.changeListeners = [];
36+
var newValue = value;
37+
var oldValue = null;
38+
notifyListeners(this, {
39+
type: "update",
40+
object: this,
41+
newValue: newValue,
42+
oldValue: oldValue
43+
});
44+
}
45+
ObservableValue.prototype.observe = function (handler, fireImmediately) { };
46+
return ObservableValue;
47+
}());
48+
exports.ObservableValue = ObservableValue;
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
=== tests/cases/compiler/noCrashOnThisTypeUsage.ts ===
2+
interface IListenable {
3+
>IListenable : Symbol(IListenable, Decl(noCrashOnThisTypeUsage.ts, 0, 0))
4+
5+
changeListeners: Function[] | null
6+
>changeListeners : Symbol(IListenable.changeListeners, Decl(noCrashOnThisTypeUsage.ts, 0, 23))
7+
>Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
8+
9+
observe(handler: (change: any, oldValue?: any) => void, fireImmediately?: boolean): void
10+
>observe : Symbol(IListenable.observe, Decl(noCrashOnThisTypeUsage.ts, 1, 38))
11+
>handler : Symbol(handler, Decl(noCrashOnThisTypeUsage.ts, 2, 12))
12+
>change : Symbol(change, Decl(noCrashOnThisTypeUsage.ts, 2, 22))
13+
>oldValue : Symbol(oldValue, Decl(noCrashOnThisTypeUsage.ts, 2, 34))
14+
>fireImmediately : Symbol(fireImmediately, Decl(noCrashOnThisTypeUsage.ts, 2, 59))
15+
}
16+
17+
function notifyListeners<T>(listenable: IListenable, change: T) {
18+
>notifyListeners : Symbol(notifyListeners, Decl(noCrashOnThisTypeUsage.ts, 3, 1))
19+
>T : Symbol(T, Decl(noCrashOnThisTypeUsage.ts, 5, 25))
20+
>listenable : Symbol(listenable, Decl(noCrashOnThisTypeUsage.ts, 5, 28))
21+
>IListenable : Symbol(IListenable, Decl(noCrashOnThisTypeUsage.ts, 0, 0))
22+
>change : Symbol(change, Decl(noCrashOnThisTypeUsage.ts, 5, 52))
23+
>T : Symbol(T, Decl(noCrashOnThisTypeUsage.ts, 5, 25))
24+
}
25+
26+
export class ObservableValue<T> {
27+
>ObservableValue : Symbol(ObservableValue, Decl(noCrashOnThisTypeUsage.ts, 6, 1))
28+
>T : Symbol(T, Decl(noCrashOnThisTypeUsage.ts, 8, 29))
29+
30+
constructor(
31+
public value: T
32+
>value : Symbol(ObservableValue.value, Decl(noCrashOnThisTypeUsage.ts, 9, 16))
33+
>T : Symbol(T, Decl(noCrashOnThisTypeUsage.ts, 8, 29))
34+
35+
) {
36+
const newValue: T = value;
37+
>newValue : Symbol(newValue, Decl(noCrashOnThisTypeUsage.ts, 12, 13))
38+
>T : Symbol(T, Decl(noCrashOnThisTypeUsage.ts, 8, 29))
39+
>value : Symbol(value, Decl(noCrashOnThisTypeUsage.ts, 9, 16))
40+
41+
const oldValue: any = null;
42+
>oldValue : Symbol(oldValue, Decl(noCrashOnThisTypeUsage.ts, 13, 13))
43+
44+
notifyListeners(this, {
45+
>notifyListeners : Symbol(notifyListeners, Decl(noCrashOnThisTypeUsage.ts, 3, 1))
46+
>this : Symbol(ObservableValue, Decl(noCrashOnThisTypeUsage.ts, 6, 1))
47+
48+
type: "update",
49+
>type : Symbol(type, Decl(noCrashOnThisTypeUsage.ts, 14, 31))
50+
51+
object: this,
52+
>object : Symbol(object, Decl(noCrashOnThisTypeUsage.ts, 15, 27))
53+
>this : Symbol(ObservableValue, Decl(noCrashOnThisTypeUsage.ts, 6, 1))
54+
55+
newValue,
56+
>newValue : Symbol(newValue, Decl(noCrashOnThisTypeUsage.ts, 16, 25))
57+
58+
oldValue
59+
>oldValue : Symbol(oldValue, Decl(noCrashOnThisTypeUsage.ts, 17, 21))
60+
61+
});
62+
}
63+
changeListeners: Function[] | null = [];
64+
>changeListeners : Symbol(ObservableValue.changeListeners, Decl(noCrashOnThisTypeUsage.ts, 20, 5))
65+
>Function : Symbol(Function, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
66+
67+
observe(handler: (change: any, oldValue?: any) => void, fireImmediately?: boolean) {}
68+
>observe : Symbol(ObservableValue.observe, Decl(noCrashOnThisTypeUsage.ts, 21, 44))
69+
>handler : Symbol(handler, Decl(noCrashOnThisTypeUsage.ts, 22, 12))
70+
>change : Symbol(change, Decl(noCrashOnThisTypeUsage.ts, 22, 22))
71+
>oldValue : Symbol(oldValue, Decl(noCrashOnThisTypeUsage.ts, 22, 34))
72+
>fireImmediately : Symbol(fireImmediately, Decl(noCrashOnThisTypeUsage.ts, 22, 59))
73+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
=== tests/cases/compiler/noCrashOnThisTypeUsage.ts ===
2+
interface IListenable {
3+
>IListenable : IListenable
4+
5+
changeListeners: Function[] | null
6+
>changeListeners : Function[] | null
7+
>Function : Function
8+
>null : null
9+
10+
observe(handler: (change: any, oldValue?: any) => void, fireImmediately?: boolean): void
11+
>observe : (handler: (change: any, oldValue?: any) => void, fireImmediately?: boolean | undefined) => void
12+
>handler : (change: any, oldValue?: any) => void
13+
>change : any
14+
>oldValue : any
15+
>fireImmediately : boolean | undefined
16+
}
17+
18+
function notifyListeners<T>(listenable: IListenable, change: T) {
19+
>notifyListeners : <T>(listenable: IListenable, change: T) => void
20+
>T : T
21+
>listenable : IListenable
22+
>IListenable : IListenable
23+
>change : T
24+
>T : T
25+
}
26+
27+
export class ObservableValue<T> {
28+
>ObservableValue : ObservableValue<T>
29+
>T : T
30+
31+
constructor(
32+
public value: T
33+
>value : T
34+
>T : T
35+
36+
) {
37+
const newValue: T = value;
38+
>newValue : T
39+
>T : T
40+
>value : T
41+
42+
const oldValue: any = null;
43+
>oldValue : any
44+
>null : null
45+
46+
notifyListeners(this, {
47+
>notifyListeners(this, { type: "update", object: this, newValue, oldValue }) : void
48+
>notifyListeners : <T>(listenable: IListenable, change: T) => void
49+
>this : this
50+
>{ type: "update", object: this, newValue, oldValue } : { type: string; object: this; newValue: T; oldValue: any; }
51+
52+
type: "update",
53+
>type : string
54+
>"update" : "update"
55+
56+
object: this,
57+
>object : this
58+
>this : this
59+
60+
newValue,
61+
>newValue : T
62+
63+
oldValue
64+
>oldValue : any
65+
66+
});
67+
}
68+
changeListeners: Function[] | null = [];
69+
>changeListeners : Function[] | null
70+
>Function : Function
71+
>null : null
72+
>[] : never[]
73+
74+
observe(handler: (change: any, oldValue?: any) => void, fireImmediately?: boolean) {}
75+
>observe : (handler: (change: any, oldValue?: any) => void, fireImmediately?: boolean | undefined) => void
76+
>handler : (change: any, oldValue?: any) => void
77+
>change : any
78+
>oldValue : any
79+
>fireImmediately : boolean | undefined
80+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// @strict: true
2+
3+
interface IListenable {
4+
changeListeners: Function[] | null
5+
observe(handler: (change: any, oldValue?: any) => void, fireImmediately?: boolean): void
6+
}
7+
8+
function notifyListeners<T>(listenable: IListenable, change: T) {
9+
}
10+
11+
export class ObservableValue<T> {
12+
constructor(
13+
public value: T
14+
) {
15+
const newValue: T = value;
16+
const oldValue: any = null;
17+
notifyListeners(this, {
18+
type: "update",
19+
object: this,
20+
newValue,
21+
oldValue
22+
});
23+
}
24+
changeListeners: Function[] | null = [];
25+
observe(handler: (change: any, oldValue?: any) => void, fireImmediately?: boolean) {}
26+
}

0 commit comments

Comments
 (0)