Skip to content

Commit ca237fe

Browse files
committed
Fix bug caused by using getApparentType in getBaseSignature.
Resulted in inferring wrapper types (meaning Number for number) in some cases. Also adds test that catches the bug.
1 parent a17c2e9 commit ca237fe

5 files changed

+463
-3
lines changed

src/compiler/checker.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6905,6 +6905,10 @@ namespace ts {
69056905
return type.resolvedApparentType || (type.resolvedApparentType = getTypeWithThisArgument(type, type, /*apparentType*/ true));
69066906
}
69076907

6908+
function getApparentTypeOfInstantiableType(type: InstantiableType) {
6909+
return isGenericTypeParameter(type) ? getApparentTypeOfGenericTypeParameter(type) : getBaseConstraintOfType(type);
6910+
}
6911+
69086912
function getApparentTypeOfGenericTypeParameter(type: GenericTypeParameter) {
69096913
const localTypeArgs = map(type.localTypeParameters, getApparentType);
69106914
const outerTypeArgs = type.mapper && instantiateTypes(type.outerTypeParameters, type.mapper);
@@ -6964,8 +6968,7 @@ namespace ts {
69646968
* type itself. Note that the apparent type of a union type is the union type itself.
69656969
*/
69666970
function getApparentType(type: Type): Type {
6967-
const t = isGenericTypeParameter(type) ? getApparentTypeOfGenericTypeParameter(type) :
6968-
type.flags & TypeFlags.Instantiable ? getBaseConstraintOfType(type) || emptyObjectType : type;
6971+
const t = type.flags & TypeFlags.Instantiable ? getApparentTypeOfInstantiableType(type) || emptyObjectType : type;
69696972
return t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(<IntersectionType>t) :
69706973
t.flags & TypeFlags.StringLike ? globalStringType :
69716974
t.flags & TypeFlags.NumberLike ? globalNumberType :
@@ -7622,7 +7625,7 @@ namespace ts {
76227625
// for generic type parameters just erase the child type parameters, not the generic type parameter itself
76237626
// because generic type parameters are an object type that can be inferred
76247627
const typeEraser = createTypeEraser(flatMap(typeParameters, tp => isGenericTypeParameter(tp) ? tp.localTypeParameters : tp));
7625-
const baseConstraints = map(typeParameters, tp => instantiateType(getApparentType(tp), typeEraser) || emptyObjectType);
7628+
const baseConstraints = map(typeParameters, tp => instantiateType(getApparentTypeOfInstantiableType(tp), typeEraser) || emptyObjectType);
76267629
return instantiateSignature(signature, createTypeMapper(typeParameters, baseConstraints), /*eraseTypeParameters*/ true);
76277630
}
76287631
return signature;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//// [getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts]
2+
export declare function f1<T>(cb: <S extends number>(x: S) => T): T;
3+
export declare function f2<T>(cb: <S extends string>(x: S) => T): T;
4+
export declare function f3<T>(cb: <S extends symbol>(x: S) => T): T;
5+
export declare function f4<T>(cb: <S extends number | string | symbol>(x: S) => T): T;
6+
export declare function f5<T, O>(cb: <S extends keyof O>(x: S) => T, obj: O): keyof O;
7+
export declare function f6<T, O>(cb: <S extends string & keyof O>(x: S) => T, obj: O): T;
8+
export declare function f7<T, O>(cb: <S extends Extract<keyof O, string>>(x: S) => T, obj: O): T;
9+
10+
const x1 = f1(x => x);
11+
const expectedx1: number = x1;
12+
13+
let x2 = f2(x => x);
14+
const expectedx2: string = x2;
15+
16+
let x3 = f3(x => x);
17+
const expectedx3: symbol = x3;
18+
19+
let x4 = f4(x => x);
20+
const expectedx4: number | string | symbol = x4;
21+
22+
declare const symProp: unique symbol
23+
declare const obj: {
24+
prop: string,
25+
[symProp]: symbol,
26+
[index: number]: number
27+
}
28+
29+
30+
let x5 = f5((x) => x, obj);
31+
const expectedx5: number | string | symbol = x5;
32+
33+
let x6 = f6(x => x, obj);
34+
const expectedx6: string = x6;
35+
36+
let x7 = f7(x => x, obj);
37+
const expectedx7: string = x7;
38+
39+
//// [getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.js]
40+
"use strict";
41+
exports.__esModule = true;
42+
var x1 = f1(function (x) { return x; });
43+
var expectedx1 = x1;
44+
var x2 = f2(function (x) { return x; });
45+
var expectedx2 = x2;
46+
var x3 = f3(function (x) { return x; });
47+
var expectedx3 = x3;
48+
var x4 = f4(function (x) { return x; });
49+
var expectedx4 = x4;
50+
var x5 = f5(function (x) { return x; }, obj);
51+
var expectedx5 = x5;
52+
var x6 = f6(function (x) { return x; }, obj);
53+
var expectedx6 = x6;
54+
var x7 = f7(function (x) { return x; }, obj);
55+
var expectedx7 = x7;
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
=== tests/cases/compiler/getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts ===
2+
export declare function f1<T>(cb: <S extends number>(x: S) => T): T;
3+
>f1 : Symbol(f1, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 0, 0))
4+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 0, 27))
5+
>cb : Symbol(cb, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 0, 30))
6+
>S : Symbol(S, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 0, 35))
7+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 0, 53))
8+
>S : Symbol(S, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 0, 35))
9+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 0, 27))
10+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 0, 27))
11+
12+
export declare function f2<T>(cb: <S extends string>(x: S) => T): T;
13+
>f2 : Symbol(f2, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 0, 68))
14+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 1, 27))
15+
>cb : Symbol(cb, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 1, 30))
16+
>S : Symbol(S, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 1, 35))
17+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 1, 53))
18+
>S : Symbol(S, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 1, 35))
19+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 1, 27))
20+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 1, 27))
21+
22+
export declare function f3<T>(cb: <S extends symbol>(x: S) => T): T;
23+
>f3 : Symbol(f3, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 1, 68))
24+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 2, 27))
25+
>cb : Symbol(cb, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 2, 30))
26+
>S : Symbol(S, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 2, 35))
27+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 2, 53))
28+
>S : Symbol(S, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 2, 35))
29+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 2, 27))
30+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 2, 27))
31+
32+
export declare function f4<T>(cb: <S extends number | string | symbol>(x: S) => T): T;
33+
>f4 : Symbol(f4, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 2, 68))
34+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 3, 27))
35+
>cb : Symbol(cb, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 3, 30))
36+
>S : Symbol(S, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 3, 35))
37+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 3, 71))
38+
>S : Symbol(S, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 3, 35))
39+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 3, 27))
40+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 3, 27))
41+
42+
export declare function f5<T, O>(cb: <S extends keyof O>(x: S) => T, obj: O): keyof O;
43+
>f5 : Symbol(f5, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 3, 86))
44+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 4, 27))
45+
>O : Symbol(O, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 4, 29))
46+
>cb : Symbol(cb, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 4, 33))
47+
>S : Symbol(S, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 4, 38))
48+
>O : Symbol(O, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 4, 29))
49+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 4, 57))
50+
>S : Symbol(S, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 4, 38))
51+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 4, 27))
52+
>obj : Symbol(obj, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 4, 68))
53+
>O : Symbol(O, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 4, 29))
54+
>O : Symbol(O, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 4, 29))
55+
56+
export declare function f6<T, O>(cb: <S extends string & keyof O>(x: S) => T, obj: O): T;
57+
>f6 : Symbol(f6, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 4, 86))
58+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 5, 27))
59+
>O : Symbol(O, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 5, 29))
60+
>cb : Symbol(cb, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 5, 33))
61+
>S : Symbol(S, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 5, 38))
62+
>O : Symbol(O, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 5, 29))
63+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 5, 66))
64+
>S : Symbol(S, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 5, 38))
65+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 5, 27))
66+
>obj : Symbol(obj, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 5, 77))
67+
>O : Symbol(O, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 5, 29))
68+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 5, 27))
69+
70+
export declare function f7<T, O>(cb: <S extends Extract<keyof O, string>>(x: S) => T, obj: O): T;
71+
>f7 : Symbol(f7, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 5, 89))
72+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 6, 27))
73+
>O : Symbol(O, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 6, 29))
74+
>cb : Symbol(cb, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 6, 33))
75+
>S : Symbol(S, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 6, 38))
76+
>Extract : Symbol(Extract, Decl(lib.d.ts, --, --))
77+
>O : Symbol(O, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 6, 29))
78+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 6, 74))
79+
>S : Symbol(S, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 6, 38))
80+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 6, 27))
81+
>obj : Symbol(obj, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 6, 85))
82+
>O : Symbol(O, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 6, 29))
83+
>T : Symbol(T, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 6, 27))
84+
85+
const x1 = f1(x => x);
86+
>x1 : Symbol(x1, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 8, 5))
87+
>f1 : Symbol(f1, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 0, 0))
88+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 8, 14))
89+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 8, 14))
90+
91+
const expectedx1: number = x1;
92+
>expectedx1 : Symbol(expectedx1, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 9, 5))
93+
>x1 : Symbol(x1, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 8, 5))
94+
95+
let x2 = f2(x => x);
96+
>x2 : Symbol(x2, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 11, 3))
97+
>f2 : Symbol(f2, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 0, 68))
98+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 11, 12))
99+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 11, 12))
100+
101+
const expectedx2: string = x2;
102+
>expectedx2 : Symbol(expectedx2, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 12, 5))
103+
>x2 : Symbol(x2, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 11, 3))
104+
105+
let x3 = f3(x => x);
106+
>x3 : Symbol(x3, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 14, 3))
107+
>f3 : Symbol(f3, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 1, 68))
108+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 14, 12))
109+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 14, 12))
110+
111+
const expectedx3: symbol = x3;
112+
>expectedx3 : Symbol(expectedx3, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 15, 5))
113+
>x3 : Symbol(x3, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 14, 3))
114+
115+
let x4 = f4(x => x);
116+
>x4 : Symbol(x4, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 17, 3))
117+
>f4 : Symbol(f4, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 2, 68))
118+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 17, 12))
119+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 17, 12))
120+
121+
const expectedx4: number | string | symbol = x4;
122+
>expectedx4 : Symbol(expectedx4, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 18, 5))
123+
>x4 : Symbol(x4, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 17, 3))
124+
125+
declare const symProp: unique symbol
126+
>symProp : Symbol(symProp, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 20, 13))
127+
128+
declare const obj: {
129+
>obj : Symbol(obj, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 21, 13))
130+
131+
prop: string,
132+
>prop : Symbol(prop, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 21, 20))
133+
134+
[symProp]: symbol,
135+
>[symProp] : Symbol([symProp], Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 22, 17))
136+
>symProp : Symbol(symProp, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 20, 13))
137+
138+
[index: number]: number
139+
>index : Symbol(index, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 24, 5))
140+
}
141+
142+
143+
let x5 = f5((x) => x, obj);
144+
>x5 : Symbol(x5, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 28, 3))
145+
>f5 : Symbol(f5, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 3, 86))
146+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 28, 13))
147+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 28, 13))
148+
>obj : Symbol(obj, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 21, 13))
149+
150+
const expectedx5: number | string | symbol = x5;
151+
>expectedx5 : Symbol(expectedx5, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 29, 5))
152+
>x5 : Symbol(x5, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 28, 3))
153+
154+
let x6 = f6(x => x, obj);
155+
>x6 : Symbol(x6, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 31, 3))
156+
>f6 : Symbol(f6, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 4, 86))
157+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 31, 12))
158+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 31, 12))
159+
>obj : Symbol(obj, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 21, 13))
160+
161+
const expectedx6: string = x6;
162+
>expectedx6 : Symbol(expectedx6, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 32, 5))
163+
>x6 : Symbol(x6, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 31, 3))
164+
165+
let x7 = f7(x => x, obj);
166+
>x7 : Symbol(x7, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 34, 3))
167+
>f7 : Symbol(f7, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 5, 89))
168+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 34, 12))
169+
>x : Symbol(x, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 34, 12))
170+
>obj : Symbol(obj, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 21, 13))
171+
172+
const expectedx7: string = x7;
173+
>expectedx7 : Symbol(expectedx7, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 35, 5))
174+
>x7 : Symbol(x7, Decl(getBaseSignatureShouldNotGetWrapperTypeOfPrimitives.ts, 34, 3))
175+

0 commit comments

Comments
 (0)