Skip to content

Commit 41226d0

Browse files
authored
Merge pull request #14141 from Microsoft/contextualThisType
Typed 'this' in object literal methods
2 parents 3295ca3 + 258bb4f commit 41226d0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2574
-394
lines changed

src/compiler/checker.ts

+211-154
Large diffs are not rendered by default.

src/compiler/types.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,8 @@
519519
/* @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes)
520520
/* @internal */ flowNode?: FlowNode; // Associated FlowNode (initialized by binding)
521521
/* @internal */ emitNode?: EmitNode; // Associated EmitNode (initialized by transforms)
522+
/* @internal */ contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution
523+
/* @internal */ contextualMapper?: TypeMapper; // Mapper for contextual type
522524
}
523525

524526
export interface NodeArray<T extends Node> extends Array<T>, TextRange {
@@ -963,7 +965,6 @@
963965

964966
export interface Expression extends Node {
965967
_expressionBrand: any;
966-
contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution
967968
}
968969

969970
export interface OmittedExpression extends Expression {

src/lib/es5.d.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -147,22 +147,22 @@ interface ObjectConstructor {
147147
* @param o Object to use as a prototype. May be null
148148
* @param properties JavaScript object that contains one or more property descriptors.
149149
*/
150-
create(o: object | null, properties: PropertyDescriptorMap): any;
150+
create(o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any;
151151

152152
/**
153153
* Adds a property to an object, or modifies attributes of an existing property.
154154
* @param o Object on which to add or modify the property. This can be a native JavaScript object (that is, a user-defined object or a built in object) or a DOM object.
155155
* @param p The property name.
156156
* @param attributes Descriptor for the property. It can be for a data property or an accessor property.
157157
*/
158-
defineProperty(o: any, p: string, attributes: PropertyDescriptor): any;
158+
defineProperty(o: any, p: string, attributes: PropertyDescriptor & ThisType<any>): any;
159159

160160
/**
161161
* Adds one or more properties to an object, and/or modifies attributes of existing properties.
162162
* @param o Object on which to add or modify the properties. This can be a native JavaScript object or a DOM object.
163163
* @param properties JavaScript object that contains one or more descriptor objects. Each descriptor object describes a data property or an accessor property.
164164
*/
165-
defineProperties(o: any, properties: PropertyDescriptorMap): any;
165+
defineProperties(o: any, properties: PropertyDescriptorMap & ThisType<any>): any;
166166

167167
/**
168168
* Prevents the modification of attributes of existing properties, and prevents the addition of new properties.
@@ -1366,6 +1366,11 @@ type Record<K extends string, T> = {
13661366
[P in K]: T;
13671367
}
13681368

1369+
/**
1370+
* Marker for contextual 'this' type
1371+
*/
1372+
interface ThisType<T> { }
1373+
13691374
/**
13701375
* Represents a raw buffer of binary data, which is used to store data for the
13711376
* different typed arrays. ArrayBuffers cannot be read from or written to directly,

tests/baselines/reference/declarationEmitThisPredicates02.errors.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredic
1313
m(): this is Foo {
1414
~~~~
1515
!!! error TS2526: A 'this' type is available only in a non-static member of a class or interface.
16-
let dis = this as Foo;
16+
let dis = this as {} as Foo;
1717
return dis.a != null && dis.b != null && dis.c != null;
1818
}
1919
}

tests/baselines/reference/declarationEmitThisPredicates02.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export interface Foo {
88

99
export const obj = {
1010
m(): this is Foo {
11-
let dis = this as Foo;
11+
let dis = this as {} as Foo;
1212
return dis.a != null && dis.b != null && dis.c != null;
1313
}
1414
}

tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredic
1616
m(): this is Foo {
1717
~~~~
1818
!!! error TS2526: A 'this' type is available only in a non-static member of a class or interface.
19-
let dis = this as Foo;
19+
let dis = this as {} as Foo;
2020
return dis.a != null && dis.b != null && dis.c != null;
2121
}
2222
}

tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ interface Foo {
88

99
export const obj = {
1010
m(): this is Foo {
11-
let dis = this as Foo;
11+
let dis = this as {} as Foo;
1212
return dis.a != null && dis.b != null && dis.c != null;
1313
}
1414
}

tests/baselines/reference/getterSetterNonAccessor.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ function setFunc(v){}
99

1010
Object.defineProperty({}, "0", <PropertyDescriptor>({
1111
>Object.defineProperty({}, "0", <PropertyDescriptor>({ get: getFunc, set: setFunc, configurable: true })) : any
12-
>Object.defineProperty : (o: any, p: string, attributes: PropertyDescriptor) => any
12+
>Object.defineProperty : (o: any, p: string, attributes: PropertyDescriptor & ThisType<any>) => any
1313
>Object : ObjectConstructor
14-
>defineProperty : (o: any, p: string, attributes: PropertyDescriptor) => any
14+
>defineProperty : (o: any, p: string, attributes: PropertyDescriptor & ThisType<any>) => any
1515
>{} : {}
1616
>"0" : "0"
1717
><PropertyDescriptor>({ get: getFunc, set: setFunc, configurable: true }) : PropertyDescriptor

tests/baselines/reference/looseThisTypeInFunctions.errors.txt

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(21,1): error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(this: void, m: number) => number'.
1+
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(22,1): error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(this: void, m: number) => number'.
22
The 'this' types of each signature are incompatible.
33
Type 'void' is not assignable to type 'C'.
4-
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(33,28): error TS2339: Property 'length' does not exist on type 'number'.
5-
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(37,9): error TS2684: The 'this' context of type 'void' is not assignable to method's 'this' of type 'I'.
6-
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,20): error TS2339: Property 'length' does not exist on type 'number'.
4+
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(26,27): error TS2339: Property 'length' does not exist on type 'number'.
5+
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(34,28): error TS2339: Property 'length' does not exist on type 'number'.
6+
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(38,9): error TS2684: The 'this' context of type 'void' is not assignable to method's 'this' of type 'I'.
7+
tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(47,20): error TS2339: Property 'length' does not exist on type 'number'.
78

89

9-
==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (4 errors) ====
10+
==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (5 errors) ====
11+
1012
interface I {
1113
n: number;
1214
explicitThis(this: this, m: number): number;
@@ -36,6 +38,8 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,20): error
3638
n: 101,
3739
explicitThis: function (m: number) {
3840
return m + this.n.length; // error, 'length' does not exist on 'number'
41+
~~~~~~
42+
!!! error TS2339: Property 'length' does not exist on type 'number'.
3943
},
4044
implicitThis(m: number): number { return m; }
4145
};

tests/baselines/reference/looseThisTypeInFunctions.js

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//// [looseThisTypeInFunctions.ts]
2+
23
interface I {
34
n: number;
45
explicitThis(this: this, m: number): number;

tests/baselines/reference/objectCreate.types

+20-20
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@ declare var union: null | { a: number, b: string };
99
var n = Object.create(null); // object
1010
>n : any
1111
>Object.create(null) : any
12-
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
12+
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
1313
>Object : ObjectConstructor
14-
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
14+
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
1515
>null : null
1616

1717
var t = Object.create({ a: 1, b: "" }); // {a: number, b: string }
1818
>t : any
1919
>Object.create({ a: 1, b: "" }) : any
20-
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
20+
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
2121
>Object : ObjectConstructor
22-
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
22+
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
2323
>{ a: 1, b: "" } : { a: number; b: string; }
2424
>a : number
2525
>1 : 1
@@ -29,43 +29,43 @@ var t = Object.create({ a: 1, b: "" }); // {a: number, b: string }
2929
var u = Object.create(union); // object | {a: number, b: string }
3030
>u : any
3131
>Object.create(union) : any
32-
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
32+
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
3333
>Object : ObjectConstructor
34-
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
34+
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
3535
>union : { a: number; b: string; } | null
3636

3737
var e = Object.create({}); // {}
3838
>e : any
3939
>Object.create({}) : any
40-
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
40+
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
4141
>Object : ObjectConstructor
42-
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
42+
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
4343
>{} : {}
4444

4545
var o = Object.create(<object>{}); // object
4646
>o : any
4747
>Object.create(<object>{}) : any
48-
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
48+
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
4949
>Object : ObjectConstructor
50-
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
50+
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
5151
><object>{} : object
5252
>{} : {}
5353

5454
var a = Object.create(null, {}); // any
5555
>a : any
5656
>Object.create(null, {}) : any
57-
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
57+
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
5858
>Object : ObjectConstructor
59-
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
59+
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
6060
>null : null
6161
>{} : {}
6262

6363
var a = Object.create({ a: 1, b: "" }, {});
6464
>a : any
6565
>Object.create({ a: 1, b: "" }, {}) : any
66-
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
66+
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
6767
>Object : ObjectConstructor
68-
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
68+
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
6969
>{ a: 1, b: "" } : { a: number; b: string; }
7070
>a : number
7171
>1 : 1
@@ -76,27 +76,27 @@ var a = Object.create({ a: 1, b: "" }, {});
7676
var a = Object.create(union, {});
7777
>a : any
7878
>Object.create(union, {}) : any
79-
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
79+
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
8080
>Object : ObjectConstructor
81-
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
81+
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
8282
>union : { a: number; b: string; } | null
8383
>{} : {}
8484

8585
var a = Object.create({}, {});
8686
>a : any
8787
>Object.create({}, {}) : any
88-
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
88+
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
8989
>Object : ObjectConstructor
90-
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
90+
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
9191
>{} : {}
9292
>{} : {}
9393

9494
var a = Object.create(<object>{}, {});
9595
>a : any
9696
>Object.create(<object>{}, {}) : any
97-
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
97+
>Object.create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
9898
>Object : ObjectConstructor
99-
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap): any; }
99+
>create : { (o: object | null): any; (o: object | null, properties: PropertyDescriptorMap & ThisType<any>): any; }
100100
><object>{} : object
101101
>{} : {}
102102
>{} : {}

tests/baselines/reference/objectCreate2.types

+20-20
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@ declare var union: null | { a: number, b: string };
99
var n = Object.create(null); // any
1010
>n : any
1111
>Object.create(null) : any
12-
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
12+
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
1313
>Object : ObjectConstructor
14-
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
14+
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
1515
>null : null
1616

1717
var t = Object.create({ a: 1, b: "" }); // {a: number, b: string }
1818
>t : any
1919
>Object.create({ a: 1, b: "" }) : any
20-
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
20+
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
2121
>Object : ObjectConstructor
22-
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
22+
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
2323
>{ a: 1, b: "" } : { a: number; b: string; }
2424
>a : number
2525
>1 : 1
@@ -29,43 +29,43 @@ var t = Object.create({ a: 1, b: "" }); // {a: number, b: string }
2929
var u = Object.create(union); // {a: number, b: string }
3030
>u : any
3131
>Object.create(union) : any
32-
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
32+
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
3333
>Object : ObjectConstructor
34-
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
34+
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
3535
>union : { a: number; b: string; }
3636

3737
var e = Object.create({}); // {}
3838
>e : any
3939
>Object.create({}) : any
40-
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
40+
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
4141
>Object : ObjectConstructor
42-
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
42+
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
4343
>{} : {}
4444

4545
var o = Object.create(<object>{}); // object
4646
>o : any
4747
>Object.create(<object>{}) : any
48-
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
48+
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
4949
>Object : ObjectConstructor
50-
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
50+
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
5151
><object>{} : object
5252
>{} : {}
5353

5454
var a = Object.create(null, {}); // any
5555
>a : any
5656
>Object.create(null, {}) : any
57-
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
57+
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
5858
>Object : ObjectConstructor
59-
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
59+
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
6060
>null : null
6161
>{} : {}
6262

6363
var a = Object.create({ a: 1, b: "" }, {});
6464
>a : any
6565
>Object.create({ a: 1, b: "" }, {}) : any
66-
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
66+
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
6767
>Object : ObjectConstructor
68-
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
68+
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
6969
>{ a: 1, b: "" } : { a: number; b: string; }
7070
>a : number
7171
>1 : 1
@@ -76,27 +76,27 @@ var a = Object.create({ a: 1, b: "" }, {});
7676
var a = Object.create(union, {});
7777
>a : any
7878
>Object.create(union, {}) : any
79-
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
79+
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
8080
>Object : ObjectConstructor
81-
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
81+
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
8282
>union : { a: number; b: string; }
8383
>{} : {}
8484

8585
var a = Object.create({}, {});
8686
>a : any
8787
>Object.create({}, {}) : any
88-
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
88+
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
8989
>Object : ObjectConstructor
90-
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
90+
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
9191
>{} : {}
9292
>{} : {}
9393

9494
var a = Object.create(<object>{}, {});
9595
>a : any
9696
>Object.create(<object>{}, {}) : any
97-
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
97+
>Object.create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
9898
>Object : ObjectConstructor
99-
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap): any; }
99+
>create : { (o: object): any; (o: object, properties: PropertyDescriptorMap & ThisType<any>): any; }
100100
><object>{} : object
101101
>{} : {}
102102
>{} : {}

0 commit comments

Comments
 (0)