Skip to content

Commit 04238e6

Browse files
authored
Fix/dependent parameters obj methods (#48110)
* Add failing test for dependent destructured variables within obj methods * Fixed an issue with dependent parameters within obj methods
1 parent 5fd0b64 commit 04238e6

File tree

5 files changed

+585
-4
lines changed

5 files changed

+585
-4
lines changed

src/compiler/checker.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -24471,7 +24471,7 @@ namespace ts {
2447124471
}
2447224472

2447324473
function getCandidateDiscriminantPropertyAccess(expr: Expression) {
24474-
if (isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference)) {
24474+
if (isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference) || isObjectLiteralMethod(reference)) {
2447524475
// When the reference is a binding pattern or function or arrow expression, we are narrowing a pesudo-reference in
2447624476
// getNarrowedTypeOfSymbol. An identifier for a destructuring variable declared in the same binding pattern or
2447724477
// parameter declared in the same parameter list is a candidate.

tests/baselines/reference/dependentDestructuredVariables.js

+175
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,101 @@ const reducer: (...args: ReducerArgs) => void = (op, args) => {
225225

226226
reducer("add", { a: 1, b: 3 });
227227
reducer("concat", { firstArr: [1, 2], secondArr: [3, 4] });
228+
229+
// repro from https://github.com/microsoft/TypeScript/pull/47190#issuecomment-1057603588
230+
231+
type FooMethod = {
232+
method(...args:
233+
[type: "str", cb: (e: string) => void] |
234+
[type: "num", cb: (e: number) => void]
235+
): void;
236+
}
237+
238+
let fooM: FooMethod = {
239+
method(type, cb) {
240+
if (type == 'num') {
241+
cb(123)
242+
} else {
243+
cb("abc")
244+
}
245+
}
246+
};
247+
248+
type FooAsyncMethod = {
249+
method(...args:
250+
[type: "str", cb: (e: string) => void] |
251+
[type: "num", cb: (e: number) => void]
252+
): Promise<any>;
253+
}
254+
255+
let fooAsyncM: FooAsyncMethod = {
256+
async method(type, cb) {
257+
if (type == 'num') {
258+
cb(123)
259+
} else {
260+
cb("abc")
261+
}
262+
}
263+
};
264+
265+
type FooGenMethod = {
266+
method(...args:
267+
[type: "str", cb: (e: string) => void] |
268+
[type: "num", cb: (e: number) => void]
269+
): Generator<any, any, any>;
270+
}
271+
272+
let fooGenM: FooGenMethod = {
273+
*method(type, cb) {
274+
if (type == 'num') {
275+
cb(123)
276+
} else {
277+
cb("abc")
278+
}
279+
}
280+
};
281+
282+
type FooAsyncGenMethod = {
283+
method(...args:
284+
[type: "str", cb: (e: string) => void] |
285+
[type: "num", cb: (e: number) => void]
286+
): AsyncGenerator<any, any, any>;
287+
}
288+
289+
let fooAsyncGenM: FooAsyncGenMethod = {
290+
async *method(type, cb) {
291+
if (type == 'num') {
292+
cb(123)
293+
} else {
294+
cb("abc")
295+
}
296+
}
297+
};
228298

229299

230300
//// [dependentDestructuredVariables.js]
231301
"use strict";
302+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
303+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
304+
return new (P || (P = Promise))(function (resolve, reject) {
305+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
306+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
307+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
308+
step((generator = generator.apply(thisArg, _arguments || [])).next());
309+
});
310+
};
311+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
312+
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
313+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
314+
var g = generator.apply(thisArg, _arguments || []), i, q = [];
315+
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
316+
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
317+
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
318+
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
319+
function fulfill(value) { resume("next", value); }
320+
function reject(value) { resume("throw", value); }
321+
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
322+
};
232323
function f10({ kind, payload }) {
233324
if (kind === 'A') {
234325
payload.toFixed();
@@ -394,6 +485,50 @@ const reducer = (op, args) => {
394485
};
395486
reducer("add", { a: 1, b: 3 });
396487
reducer("concat", { firstArr: [1, 2], secondArr: [3, 4] });
488+
let fooM = {
489+
method(type, cb) {
490+
if (type == 'num') {
491+
cb(123);
492+
}
493+
else {
494+
cb("abc");
495+
}
496+
}
497+
};
498+
let fooAsyncM = {
499+
method(type, cb) {
500+
return __awaiter(this, void 0, void 0, function* () {
501+
if (type == 'num') {
502+
cb(123);
503+
}
504+
else {
505+
cb("abc");
506+
}
507+
});
508+
}
509+
};
510+
let fooGenM = {
511+
*method(type, cb) {
512+
if (type == 'num') {
513+
cb(123);
514+
}
515+
else {
516+
cb("abc");
517+
}
518+
}
519+
};
520+
let fooAsyncGenM = {
521+
method(type, cb) {
522+
return __asyncGenerator(this, arguments, function* method_1() {
523+
if (type == 'num') {
524+
cb(123);
525+
}
526+
else {
527+
cb("abc");
528+
}
529+
});
530+
}
531+
};
397532

398533

399534
//// [dependentDestructuredVariables.d.ts]
@@ -469,3 +604,43 @@ declare type ReducerArgs = ["add", {
469604
secondArr: any[];
470605
}];
471606
declare const reducer: (...args: ReducerArgs) => void;
607+
declare type FooMethod = {
608+
method(...args: [
609+
type: "str",
610+
cb: (e: string) => void
611+
] | [
612+
type: "num",
613+
cb: (e: number) => void
614+
]): void;
615+
};
616+
declare let fooM: FooMethod;
617+
declare type FooAsyncMethod = {
618+
method(...args: [
619+
type: "str",
620+
cb: (e: string) => void
621+
] | [
622+
type: "num",
623+
cb: (e: number) => void
624+
]): Promise<any>;
625+
};
626+
declare let fooAsyncM: FooAsyncMethod;
627+
declare type FooGenMethod = {
628+
method(...args: [
629+
type: "str",
630+
cb: (e: string) => void
631+
] | [
632+
type: "num",
633+
cb: (e: number) => void
634+
]): Generator<any, any, any>;
635+
};
636+
declare let fooGenM: FooGenMethod;
637+
declare type FooAsyncGenMethod = {
638+
method(...args: [
639+
type: "str",
640+
cb: (e: string) => void
641+
] | [
642+
type: "num",
643+
cb: (e: number) => void
644+
]): AsyncGenerator<any, any, any>;
645+
};
646+
declare let fooAsyncGenM: FooAsyncGenMethod;

tests/baselines/reference/dependentDestructuredVariables.symbols

+160-3
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ interface B<T> { variant: 'b', value: Array<T> }
321321
>T : Symbol(T, Decl(dependentDestructuredVariables.ts, 128, 12))
322322
>variant : Symbol(B.variant, Decl(dependentDestructuredVariables.ts, 128, 16))
323323
>value : Symbol(B.value, Decl(dependentDestructuredVariables.ts, 128, 30))
324-
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
324+
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 3 more)
325325
>T : Symbol(T, Decl(dependentDestructuredVariables.ts, 128, 12))
326326

327327
type AB<T> = A<T> | B<T>;
@@ -342,7 +342,7 @@ declare function printValueList<T>(t: Array<T>): void;
342342
>printValueList : Symbol(printValueList, Decl(dependentDestructuredVariables.ts, 132, 43))
343343
>T : Symbol(T, Decl(dependentDestructuredVariables.ts, 134, 32))
344344
>t : Symbol(t, Decl(dependentDestructuredVariables.ts, 134, 35))
345-
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
345+
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 3 more)
346346
>T : Symbol(T, Decl(dependentDestructuredVariables.ts, 134, 32))
347347

348348
function unrefined1<T>(ab: AB<T>): void {
@@ -514,7 +514,7 @@ declare function readFile(path: string, callback: (...args: [err: null, data: un
514514
>path : Symbol(path, Decl(dependentDestructuredVariables.ts, 200, 26))
515515
>callback : Symbol(callback, Decl(dependentDestructuredVariables.ts, 200, 39))
516516
>args : Symbol(args, Decl(dependentDestructuredVariables.ts, 200, 51))
517-
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
517+
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2022.error.d.ts, --, --))
518518

519519
readFile('hello', (err, data) => {
520520
>readFile : Symbol(readFile, Decl(dependentDestructuredVariables.ts, 198, 2))
@@ -595,3 +595,160 @@ reducer("concat", { firstArr: [1, 2], secondArr: [3, 4] });
595595
>firstArr : Symbol(firstArr, Decl(dependentDestructuredVariables.ts, 225, 19))
596596
>secondArr : Symbol(secondArr, Decl(dependentDestructuredVariables.ts, 225, 37))
597597

598+
// repro from https://github.com/microsoft/TypeScript/pull/47190#issuecomment-1057603588
599+
600+
type FooMethod = {
601+
>FooMethod : Symbol(FooMethod, Decl(dependentDestructuredVariables.ts, 225, 59))
602+
603+
method(...args:
604+
>method : Symbol(method, Decl(dependentDestructuredVariables.ts, 229, 18))
605+
>args : Symbol(args, Decl(dependentDestructuredVariables.ts, 230, 9))
606+
607+
[type: "str", cb: (e: string) => void] |
608+
>e : Symbol(e, Decl(dependentDestructuredVariables.ts, 231, 23))
609+
610+
[type: "num", cb: (e: number) => void]
611+
>e : Symbol(e, Decl(dependentDestructuredVariables.ts, 232, 23))
612+
613+
): void;
614+
}
615+
616+
let fooM: FooMethod = {
617+
>fooM : Symbol(fooM, Decl(dependentDestructuredVariables.ts, 236, 3))
618+
>FooMethod : Symbol(FooMethod, Decl(dependentDestructuredVariables.ts, 225, 59))
619+
620+
method(type, cb) {
621+
>method : Symbol(method, Decl(dependentDestructuredVariables.ts, 236, 23))
622+
>type : Symbol(type, Decl(dependentDestructuredVariables.ts, 237, 9))
623+
>cb : Symbol(cb, Decl(dependentDestructuredVariables.ts, 237, 14))
624+
625+
if (type == 'num') {
626+
>type : Symbol(type, Decl(dependentDestructuredVariables.ts, 237, 9))
627+
628+
cb(123)
629+
>cb : Symbol(cb, Decl(dependentDestructuredVariables.ts, 237, 14))
630+
631+
} else {
632+
cb("abc")
633+
>cb : Symbol(cb, Decl(dependentDestructuredVariables.ts, 237, 14))
634+
}
635+
}
636+
};
637+
638+
type FooAsyncMethod = {
639+
>FooAsyncMethod : Symbol(FooAsyncMethod, Decl(dependentDestructuredVariables.ts, 244, 2))
640+
641+
method(...args:
642+
>method : Symbol(method, Decl(dependentDestructuredVariables.ts, 246, 23))
643+
>args : Symbol(args, Decl(dependentDestructuredVariables.ts, 247, 9))
644+
645+
[type: "str", cb: (e: string) => void] |
646+
>e : Symbol(e, Decl(dependentDestructuredVariables.ts, 248, 23))
647+
648+
[type: "num", cb: (e: number) => void]
649+
>e : Symbol(e, Decl(dependentDestructuredVariables.ts, 249, 23))
650+
651+
): Promise<any>;
652+
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
653+
}
654+
655+
let fooAsyncM: FooAsyncMethod = {
656+
>fooAsyncM : Symbol(fooAsyncM, Decl(dependentDestructuredVariables.ts, 253, 3))
657+
>FooAsyncMethod : Symbol(FooAsyncMethod, Decl(dependentDestructuredVariables.ts, 244, 2))
658+
659+
async method(type, cb) {
660+
>method : Symbol(method, Decl(dependentDestructuredVariables.ts, 253, 33))
661+
>type : Symbol(type, Decl(dependentDestructuredVariables.ts, 254, 15))
662+
>cb : Symbol(cb, Decl(dependentDestructuredVariables.ts, 254, 20))
663+
664+
if (type == 'num') {
665+
>type : Symbol(type, Decl(dependentDestructuredVariables.ts, 254, 15))
666+
667+
cb(123)
668+
>cb : Symbol(cb, Decl(dependentDestructuredVariables.ts, 254, 20))
669+
670+
} else {
671+
cb("abc")
672+
>cb : Symbol(cb, Decl(dependentDestructuredVariables.ts, 254, 20))
673+
}
674+
}
675+
};
676+
677+
type FooGenMethod = {
678+
>FooGenMethod : Symbol(FooGenMethod, Decl(dependentDestructuredVariables.ts, 261, 2))
679+
680+
method(...args:
681+
>method : Symbol(method, Decl(dependentDestructuredVariables.ts, 263, 21))
682+
>args : Symbol(args, Decl(dependentDestructuredVariables.ts, 264, 9))
683+
684+
[type: "str", cb: (e: string) => void] |
685+
>e : Symbol(e, Decl(dependentDestructuredVariables.ts, 265, 23))
686+
687+
[type: "num", cb: (e: number) => void]
688+
>e : Symbol(e, Decl(dependentDestructuredVariables.ts, 266, 23))
689+
690+
): Generator<any, any, any>;
691+
>Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --))
692+
}
693+
694+
let fooGenM: FooGenMethod = {
695+
>fooGenM : Symbol(fooGenM, Decl(dependentDestructuredVariables.ts, 270, 3))
696+
>FooGenMethod : Symbol(FooGenMethod, Decl(dependentDestructuredVariables.ts, 261, 2))
697+
698+
*method(type, cb) {
699+
>method : Symbol(method, Decl(dependentDestructuredVariables.ts, 270, 29))
700+
>type : Symbol(type, Decl(dependentDestructuredVariables.ts, 271, 10))
701+
>cb : Symbol(cb, Decl(dependentDestructuredVariables.ts, 271, 15))
702+
703+
if (type == 'num') {
704+
>type : Symbol(type, Decl(dependentDestructuredVariables.ts, 271, 10))
705+
706+
cb(123)
707+
>cb : Symbol(cb, Decl(dependentDestructuredVariables.ts, 271, 15))
708+
709+
} else {
710+
cb("abc")
711+
>cb : Symbol(cb, Decl(dependentDestructuredVariables.ts, 271, 15))
712+
}
713+
}
714+
};
715+
716+
type FooAsyncGenMethod = {
717+
>FooAsyncGenMethod : Symbol(FooAsyncGenMethod, Decl(dependentDestructuredVariables.ts, 278, 2))
718+
719+
method(...args:
720+
>method : Symbol(method, Decl(dependentDestructuredVariables.ts, 280, 26))
721+
>args : Symbol(args, Decl(dependentDestructuredVariables.ts, 281, 9))
722+
723+
[type: "str", cb: (e: string) => void] |
724+
>e : Symbol(e, Decl(dependentDestructuredVariables.ts, 282, 23))
725+
726+
[type: "num", cb: (e: number) => void]
727+
>e : Symbol(e, Decl(dependentDestructuredVariables.ts, 283, 23))
728+
729+
): AsyncGenerator<any, any, any>;
730+
>AsyncGenerator : Symbol(AsyncGenerator, Decl(lib.es2018.asyncgenerator.d.ts, --, --))
731+
}
732+
733+
let fooAsyncGenM: FooAsyncGenMethod = {
734+
>fooAsyncGenM : Symbol(fooAsyncGenM, Decl(dependentDestructuredVariables.ts, 287, 3))
735+
>FooAsyncGenMethod : Symbol(FooAsyncGenMethod, Decl(dependentDestructuredVariables.ts, 278, 2))
736+
737+
async *method(type, cb) {
738+
>method : Symbol(method, Decl(dependentDestructuredVariables.ts, 287, 39))
739+
>type : Symbol(type, Decl(dependentDestructuredVariables.ts, 288, 16))
740+
>cb : Symbol(cb, Decl(dependentDestructuredVariables.ts, 288, 21))
741+
742+
if (type == 'num') {
743+
>type : Symbol(type, Decl(dependentDestructuredVariables.ts, 288, 16))
744+
745+
cb(123)
746+
>cb : Symbol(cb, Decl(dependentDestructuredVariables.ts, 288, 21))
747+
748+
} else {
749+
cb("abc")
750+
>cb : Symbol(cb, Decl(dependentDestructuredVariables.ts, 288, 21))
751+
}
752+
}
753+
};
754+

0 commit comments

Comments
 (0)