Skip to content

Commit e67da8a

Browse files
authoredMay 19, 2021
Preserve generics in contextual types for rest arguments (#44122)
* Move all getIndexedAccessType flags to AccessFlags enum * Preserve generics in contextual types for rest arguments * Add regression test
1 parent 73736d9 commit e67da8a

File tree

7 files changed

+174
-50
lines changed

7 files changed

+174
-50
lines changed
 

‎src/compiler/checker.ts

Lines changed: 40 additions & 44 deletions
Large diffs are not rendered by default.

‎src/compiler/types.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5491,17 +5491,28 @@ namespace ts {
54915491
resolvedDefaultType?: Type;
54925492
}
54935493

5494+
/* @internal */
5495+
export const enum AccessFlags {
5496+
None = 0,
5497+
IncludeUndefined = 1 << 0,
5498+
NoIndexSignatures = 1 << 1,
5499+
Writing = 1 << 2,
5500+
CacheSymbol = 1 << 3,
5501+
NoTupleBoundsCheck = 1 << 4,
5502+
ExpressionPosition = 1 << 5,
5503+
ReportDeprecated = 1 << 6,
5504+
SuppressNoImplicitAnyError = 1 << 7,
5505+
Contextual = 1 << 8,
5506+
Persistent = IncludeUndefined,
5507+
}
5508+
54945509
// Indexed access types (TypeFlags.IndexedAccess)
54955510
// Possible forms are T[xxx], xxx[T], or xxx[keyof T], where T is a type variable
54965511
export interface IndexedAccessType extends InstantiableType {
54975512
objectType: Type;
54985513
indexType: Type;
5499-
/**
5500-
* @internal
5501-
* Indicates that --noUncheckedIndexedAccess may introduce 'undefined' into
5502-
* the resulting type, depending on how type variable constraints are resolved.
5503-
*/
5504-
noUncheckedIndexedAccessCandidate: boolean;
5514+
/* @internal */
5515+
accessFlags: AccessFlags; // Only includes AccessFlags.Persistent
55055516
constraint?: Type;
55065517
simplifiedForReading?: Type;
55075518
simplifiedForWriting?: Type;

‎tests/baselines/reference/controlFlowGenericTypes.errors.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,14 @@ tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts(91,11): error TS2
149149
}
150150
return 0;
151151
};
152+
153+
// Repro from #44093
154+
155+
class EventEmitter<ET> {
156+
off<K extends keyof ET>(...args: [K, number] | [unknown, string]):void {}
157+
}
158+
function once<ET, T extends EventEmitter<ET>>(emittingObject: T, eventName: keyof ET): void {
159+
emittingObject.off(eventName, 0);
160+
emittingObject.off(eventName as typeof eventName, 0);
161+
}
152162

‎tests/baselines/reference/controlFlowGenericTypes.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,16 @@ function get<K extends keyof A>(key: K, obj: A): number {
128128
}
129129
return 0;
130130
};
131+
132+
// Repro from #44093
133+
134+
class EventEmitter<ET> {
135+
off<K extends keyof ET>(...args: [K, number] | [unknown, string]):void {}
136+
}
137+
function once<ET, T extends EventEmitter<ET>>(emittingObject: T, eventName: keyof ET): void {
138+
emittingObject.off(eventName, 0);
139+
emittingObject.off(eventName as typeof eventName, 0);
140+
}
131141

132142

133143
//// [controlFlowGenericTypes.js]
@@ -220,3 +230,19 @@ function get(key, obj) {
220230
return 0;
221231
}
222232
;
233+
// Repro from #44093
234+
var EventEmitter = /** @class */ (function () {
235+
function EventEmitter() {
236+
}
237+
EventEmitter.prototype.off = function () {
238+
var args = [];
239+
for (var _i = 0; _i < arguments.length; _i++) {
240+
args[_i] = arguments[_i];
241+
}
242+
};
243+
return EventEmitter;
244+
}());
245+
function once(emittingObject, eventName) {
246+
emittingObject.off(eventName, 0);
247+
emittingObject.off(eventName, 0);
248+
}

‎tests/baselines/reference/controlFlowGenericTypes.symbols

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,3 +367,41 @@ function get<K extends keyof A>(key: K, obj: A): number {
367367
return 0;
368368
};
369369

370+
// Repro from #44093
371+
372+
class EventEmitter<ET> {
373+
>EventEmitter : Symbol(EventEmitter, Decl(controlFlowGenericTypes.ts, 128, 2))
374+
>ET : Symbol(ET, Decl(controlFlowGenericTypes.ts, 132, 19))
375+
376+
off<K extends keyof ET>(...args: [K, number] | [unknown, string]):void {}
377+
>off : Symbol(EventEmitter.off, Decl(controlFlowGenericTypes.ts, 132, 24))
378+
>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 133, 8))
379+
>ET : Symbol(ET, Decl(controlFlowGenericTypes.ts, 132, 19))
380+
>args : Symbol(args, Decl(controlFlowGenericTypes.ts, 133, 28))
381+
>K : Symbol(K, Decl(controlFlowGenericTypes.ts, 133, 8))
382+
}
383+
function once<ET, T extends EventEmitter<ET>>(emittingObject: T, eventName: keyof ET): void {
384+
>once : Symbol(once, Decl(controlFlowGenericTypes.ts, 134, 1))
385+
>ET : Symbol(ET, Decl(controlFlowGenericTypes.ts, 135, 14))
386+
>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 135, 17))
387+
>EventEmitter : Symbol(EventEmitter, Decl(controlFlowGenericTypes.ts, 128, 2))
388+
>ET : Symbol(ET, Decl(controlFlowGenericTypes.ts, 135, 14))
389+
>emittingObject : Symbol(emittingObject, Decl(controlFlowGenericTypes.ts, 135, 46))
390+
>T : Symbol(T, Decl(controlFlowGenericTypes.ts, 135, 17))
391+
>eventName : Symbol(eventName, Decl(controlFlowGenericTypes.ts, 135, 64))
392+
>ET : Symbol(ET, Decl(controlFlowGenericTypes.ts, 135, 14))
393+
394+
emittingObject.off(eventName, 0);
395+
>emittingObject.off : Symbol(EventEmitter.off, Decl(controlFlowGenericTypes.ts, 132, 24))
396+
>emittingObject : Symbol(emittingObject, Decl(controlFlowGenericTypes.ts, 135, 46))
397+
>off : Symbol(EventEmitter.off, Decl(controlFlowGenericTypes.ts, 132, 24))
398+
>eventName : Symbol(eventName, Decl(controlFlowGenericTypes.ts, 135, 64))
399+
400+
emittingObject.off(eventName as typeof eventName, 0);
401+
>emittingObject.off : Symbol(EventEmitter.off, Decl(controlFlowGenericTypes.ts, 132, 24))
402+
>emittingObject : Symbol(emittingObject, Decl(controlFlowGenericTypes.ts, 135, 46))
403+
>off : Symbol(EventEmitter.off, Decl(controlFlowGenericTypes.ts, 132, 24))
404+
>eventName : Symbol(eventName, Decl(controlFlowGenericTypes.ts, 135, 64))
405+
>eventName : Symbol(eventName, Decl(controlFlowGenericTypes.ts, 135, 64))
406+
}
407+

‎tests/baselines/reference/controlFlowGenericTypes.types

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,3 +355,36 @@ function get<K extends keyof A>(key: K, obj: A): number {
355355

356356
};
357357

358+
// Repro from #44093
359+
360+
class EventEmitter<ET> {
361+
>EventEmitter : EventEmitter<ET>
362+
363+
off<K extends keyof ET>(...args: [K, number] | [unknown, string]):void {}
364+
>off : <K extends keyof ET>(...args: [K, number] | [unknown, string]) => void
365+
>args : [K, number] | [unknown, string]
366+
}
367+
function once<ET, T extends EventEmitter<ET>>(emittingObject: T, eventName: keyof ET): void {
368+
>once : <ET, T extends EventEmitter<ET>>(emittingObject: T, eventName: keyof ET) => void
369+
>emittingObject : T
370+
>eventName : keyof ET
371+
372+
emittingObject.off(eventName, 0);
373+
>emittingObject.off(eventName, 0) : void
374+
>emittingObject.off : <K extends keyof ET>(...args: [unknown, string] | [K, number]) => void
375+
>emittingObject : T
376+
>off : <K extends keyof ET>(...args: [unknown, string] | [K, number]) => void
377+
>eventName : keyof ET
378+
>0 : 0
379+
380+
emittingObject.off(eventName as typeof eventName, 0);
381+
>emittingObject.off(eventName as typeof eventName, 0) : void
382+
>emittingObject.off : <K extends keyof ET>(...args: [unknown, string] | [K, number]) => void
383+
>emittingObject : T
384+
>off : <K extends keyof ET>(...args: [unknown, string] | [K, number]) => void
385+
>eventName as typeof eventName : keyof ET
386+
>eventName : keyof ET
387+
>eventName : keyof ET
388+
>0 : 0
389+
}
390+

‎tests/cases/conformance/controlFlow/controlFlowGenericTypes.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,13 @@ function get<K extends keyof A>(key: K, obj: A): number {
129129
}
130130
return 0;
131131
};
132+
133+
// Repro from #44093
134+
135+
class EventEmitter<ET> {
136+
off<K extends keyof ET>(...args: [K, number] | [unknown, string]):void {}
137+
}
138+
function once<ET, T extends EventEmitter<ET>>(emittingObject: T, eventName: keyof ET): void {
139+
emittingObject.off(eventName, 0);
140+
emittingObject.off(eventName as typeof eventName, 0);
141+
}

0 commit comments

Comments
 (0)
Please sign in to comment.