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

Lines changed: 211 additions & 154 deletions
Large diffs are not rendered by default.

src/compiler/types.ts

Lines changed: 2 additions & 1 deletion
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

Lines changed: 8 additions & 3 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 9 additions & 5 deletions
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

Lines changed: 1 addition & 0 deletions
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;

0 commit comments

Comments
 (0)