Skip to content

Commit d629607

Browse files
authored
Merge pull request microsoft#21610 from Microsoft/fixSharedTypeParameters
Fix unintended sharing of type parameters
2 parents 120af86 + 8ae5f63 commit d629607

File tree

6 files changed

+118
-2
lines changed

6 files changed

+118
-2
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8705,7 +8705,7 @@ namespace ts {
87058705
const target = type.objectFlags & ObjectFlags.Instantiated ? type.target : type;
87068706
const symbol = target.symbol;
87078707
const links = getSymbolLinks(symbol);
8708-
let typeParameters = links.typeParameters;
8708+
let typeParameters = links.outerTypeParameters;
87098709
if (!typeParameters) {
87108710
// The first time an anonymous type is instantiated we compute and store a list of the type
87118711
// parameters that are in scope (and therefore potentially referenced). For type literals that
@@ -8716,7 +8716,7 @@ namespace ts {
87168716
typeParameters = symbol.flags & SymbolFlags.TypeLiteral && !target.aliasTypeArguments ?
87178717
filter(outerTypeParameters, tp => isTypeParameterPossiblyReferenced(tp, declaration)) :
87188718
outerTypeParameters;
8719-
links.typeParameters = typeParameters;
8719+
links.outerTypeParameters = typeParameters;
87208720
if (typeParameters.length) {
87218721
links.instantiations = createMap<Type>();
87228722
links.instantiations.set(getTypeListId(typeParameters), target);

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3312,6 +3312,7 @@ namespace ts {
33123312
type?: Type; // Type of value symbol
33133313
declaredType?: Type; // Type of class, interface, enum, type alias, or type parameter
33143314
typeParameters?: TypeParameter[]; // Type parameters of type alias (undefined if non-generic)
3315+
outerTypeParameters?: TypeParameter[]; // Outer type parameters of anonymous object type
33153316
inferredClassType?: Type; // Type of an inferred ES5 class
33163317
instantiations?: Map<Type>; // Instantiations of generic type alias (undefined if non-generic)
33173318
mapper?: TypeMapper; // Type mapper for instantiation alias
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//// [typeAliasFunctionTypeSharedSymbol.ts]
2+
// Repro from comment in #21496
3+
4+
function Mixin<TBase extends {new (...args: any[]): {}}>(Base: TBase) {
5+
return class extends Base {
6+
};
7+
}
8+
9+
type Mixin = ReturnTypeOf<typeof Mixin>
10+
11+
type ReturnTypeOf<V> = V extends (...args: any[])=>infer R ? R : never;
12+
13+
type Crashes = number & Mixin;
14+
15+
16+
//// [typeAliasFunctionTypeSharedSymbol.js]
17+
// Repro from comment in #21496
18+
var __extends = (this && this.__extends) || (function () {
19+
var extendStatics = Object.setPrototypeOf ||
20+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
21+
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
22+
return function (d, b) {
23+
extendStatics(d, b);
24+
function __() { this.constructor = d; }
25+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
26+
};
27+
})();
28+
function Mixin(Base) {
29+
return /** @class */ (function (_super) {
30+
__extends(class_1, _super);
31+
function class_1() {
32+
return _super !== null && _super.apply(this, arguments) || this;
33+
}
34+
return class_1;
35+
}(Base));
36+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
=== tests/cases/compiler/typeAliasFunctionTypeSharedSymbol.ts ===
2+
// Repro from comment in #21496
3+
4+
function Mixin<TBase extends {new (...args: any[]): {}}>(Base: TBase) {
5+
>Mixin : Symbol(Mixin, Decl(typeAliasFunctionTypeSharedSymbol.ts, 0, 0), Decl(typeAliasFunctionTypeSharedSymbol.ts, 5, 1))
6+
>TBase : Symbol(TBase, Decl(typeAliasFunctionTypeSharedSymbol.ts, 2, 15))
7+
>args : Symbol(args, Decl(typeAliasFunctionTypeSharedSymbol.ts, 2, 35))
8+
>Base : Symbol(Base, Decl(typeAliasFunctionTypeSharedSymbol.ts, 2, 57))
9+
>TBase : Symbol(TBase, Decl(typeAliasFunctionTypeSharedSymbol.ts, 2, 15))
10+
11+
return class extends Base {
12+
>Base : Symbol(Base, Decl(typeAliasFunctionTypeSharedSymbol.ts, 2, 57))
13+
14+
};
15+
}
16+
17+
type Mixin = ReturnTypeOf<typeof Mixin>
18+
>Mixin : Symbol(Mixin, Decl(typeAliasFunctionTypeSharedSymbol.ts, 0, 0), Decl(typeAliasFunctionTypeSharedSymbol.ts, 5, 1))
19+
>ReturnTypeOf : Symbol(ReturnTypeOf, Decl(typeAliasFunctionTypeSharedSymbol.ts, 7, 39))
20+
>Mixin : Symbol(Mixin, Decl(typeAliasFunctionTypeSharedSymbol.ts, 0, 0), Decl(typeAliasFunctionTypeSharedSymbol.ts, 5, 1))
21+
22+
type ReturnTypeOf<V> = V extends (...args: any[])=>infer R ? R : never;
23+
>ReturnTypeOf : Symbol(ReturnTypeOf, Decl(typeAliasFunctionTypeSharedSymbol.ts, 7, 39))
24+
>V : Symbol(V, Decl(typeAliasFunctionTypeSharedSymbol.ts, 9, 18))
25+
>V : Symbol(V, Decl(typeAliasFunctionTypeSharedSymbol.ts, 9, 18))
26+
>args : Symbol(args, Decl(typeAliasFunctionTypeSharedSymbol.ts, 9, 34))
27+
>R : Symbol(R, Decl(typeAliasFunctionTypeSharedSymbol.ts, 9, 56))
28+
>R : Symbol(R, Decl(typeAliasFunctionTypeSharedSymbol.ts, 9, 56))
29+
30+
type Crashes = number & Mixin;
31+
>Crashes : Symbol(Crashes, Decl(typeAliasFunctionTypeSharedSymbol.ts, 9, 71))
32+
>Mixin : Symbol(Mixin, Decl(typeAliasFunctionTypeSharedSymbol.ts, 0, 0), Decl(typeAliasFunctionTypeSharedSymbol.ts, 5, 1))
33+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
=== tests/cases/compiler/typeAliasFunctionTypeSharedSymbol.ts ===
2+
// Repro from comment in #21496
3+
4+
function Mixin<TBase extends {new (...args: any[]): {}}>(Base: TBase) {
5+
>Mixin : <TBase extends new (...args: any[]) => {}>(Base: TBase) => { new (...args: any[]): (Anonymous class); prototype: Mixin<any>.(Anonymous class); } & TBase
6+
>TBase : TBase
7+
>args : any[]
8+
>Base : TBase
9+
>TBase : TBase
10+
11+
return class extends Base {
12+
>class extends Base { } : { new (...args: any[]): (Anonymous class); prototype: Mixin<any>.(Anonymous class); } & TBase
13+
>Base : {}
14+
15+
};
16+
}
17+
18+
type Mixin = ReturnTypeOf<typeof Mixin>
19+
>Mixin : { new (...args: any[]): Mixin<new (...args: any[]) => {}>.(Anonymous class); prototype: Mixin<any>.(Anonymous class); } & (new (...args: any[]) => {})
20+
>ReturnTypeOf : ReturnTypeOf<V>
21+
>Mixin : <TBase extends new (...args: any[]) => {}>(Base: TBase) => { new (...args: any[]): (Anonymous class); prototype: Mixin<any>.(Anonymous class); } & TBase
22+
23+
type ReturnTypeOf<V> = V extends (...args: any[])=>infer R ? R : never;
24+
>ReturnTypeOf : ReturnTypeOf<V>
25+
>V : V
26+
>V : V
27+
>args : any[]
28+
>R : R
29+
>R : R
30+
31+
type Crashes = number & Mixin;
32+
>Crashes : Crashes
33+
>Mixin : { new (...args: any[]): Mixin<new (...args: any[]) => {}>.(Anonymous class); prototype: Mixin<any>.(Anonymous class); } & (new (...args: any[]) => {})
34+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Repro from comment in #21496
2+
3+
function Mixin<TBase extends {new (...args: any[]): {}}>(Base: TBase) {
4+
return class extends Base {
5+
};
6+
}
7+
8+
type Mixin = ReturnTypeOf<typeof Mixin>
9+
10+
type ReturnTypeOf<V> = V extends (...args: any[])=>infer R ? R : never;
11+
12+
type Crashes = number & Mixin;

0 commit comments

Comments
 (0)