Skip to content

Commit a3a54ce

Browse files
committed
update test
1 parent ec54884 commit a3a54ce

File tree

5 files changed

+316
-4
lines changed

5 files changed

+316
-4
lines changed

Diff for: src/compiler/checker.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -44243,15 +44243,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4424344243
const references: QueryReferences = [];
4424444244
const nodeId = getNodeId(container);
4424544245
if (!queryTypeParameterReferencesCache.has(nodeId)) {
44246-
const flowNodes = collectFlowNodes(container);
44246+
const flowNodes = collectFlowNodes(container); // >> TODO: collectFlowNodes may have duplicates
4424744247
// >> TODO: this will cause us to possibly visit the same flow nodes more than once.
4424844248
// >> Dedupe work.
44249-
flowNodes.forEach(flowNode => visitFlowNode(flowNode, collect));
44249+
flowNodes.forEach(flowNode => visitFlowNode(flowNode, collectNode));
4425044250
queryTypeParameterReferencesCache.set(nodeId, references);
4425144251
}
4425244252
return queryTypeParameterReferencesCache.get(nodeId)!;
4425344253

44254-
function collect(flow: FlowNode) {
44254+
function collectNode(flow: FlowNode) {
4425544255
const flags = flow.flags;
4425644256
// Based on `getTypeAtFlowX` functions.
4425744257
let node;

Diff for: tests/baselines/reference/dependentReturnType1.errors.txt

+41-1
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@ dependentReturnType1.ts(335,5): error TS2322: Type '1' is not assignable to type
3333
dependentReturnType1.ts(343,13): error TS2322: Type 'number' is not assignable to type 'T extends 1 ? number : T extends 2 ? string : 1 | 2'.
3434
dependentReturnType1.ts(345,9): error TS2322: Type 'string' is not assignable to type 'T extends 1 ? number : T extends 2 ? string : 1 | 2'.
3535
dependentReturnType1.ts(353,13): error TS2322: Type 'number' is not assignable to type 'string'.
36+
dependentReturnType1.ts(379,13): error TS2322: Type 'R' is not assignable to type 'ConditionalReturnType<T, R, EOp>'.
3637

3738

38-
==== dependentReturnType1.ts (30 errors) ====
39+
==== dependentReturnType1.ts (31 errors) ====
3940
interface A {
4041
1: number;
4142
2: string;
@@ -458,4 +459,43 @@ dependentReturnType1.ts(353,13): error TS2322: Type 'number' is not assignable t
458459
return ""; // Ok
459460
}
460461
return 0; // Ok
462+
}
463+
464+
// From #33912
465+
abstract class Operation<T, R> {
466+
abstract perform(t: T): R;
467+
}
468+
469+
type ConditionalReturnType<T, R, EOp extends Operation<T, R> | undefined> =
470+
EOp extends Operation<T, R> ? R : EOp extends undefined ? T | R : T | R;
471+
472+
class ConditionalOperation<T, R, EOp extends Operation<T, R> | undefined> extends Operation<T, ConditionalReturnType<T, R, EOp>> {
473+
constructor(
474+
private predicate: (value: T) => boolean,
475+
private thenOp: Operation<T, R>,
476+
private elseOp?: EOp
477+
) {
478+
super();
479+
}
480+
481+
perform(t: T): ConditionalReturnType<T, R, EOp> {
482+
if (this.predicate(t)) {
483+
return this.thenOp.perform(t); // Bad: this is assignable to all of the branches of the conditional, but we still can't return it
484+
~~~~~~
485+
!!! error TS2322: Type 'R' is not assignable to type 'ConditionalReturnType<T, R, EOp>'.
486+
} else if (typeof this.elseOp !== 'undefined') {
487+
return this.elseOp.perform(t); // Ok
488+
} else {
489+
return t; // Ok
490+
}
491+
}
492+
}
493+
494+
// Optional tuple element
495+
function tupl<T extends true | false | undefined>(x: [string, some?: T]):
496+
T extends true ? 1 : T extends false | undefined ? 2 : 1 | 2 {
497+
if (x[1]) {
498+
return 1;
499+
}
500+
return 2;
461501
}

Diff for: tests/baselines/reference/dependentReturnType1.symbols

+133
Original file line numberDiff line numberDiff line change
@@ -1004,3 +1004,136 @@ function h<T extends 1 | 2>(x: T): T extends 1 ? number : T extends 2 ? string :
10041004
}
10051005
return 0; // Ok
10061006
}
1007+
1008+
// From #33912
1009+
abstract class Operation<T, R> {
1010+
>Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 357, 1))
1011+
>T : Symbol(T, Decl(dependentReturnType1.ts, 360, 25))
1012+
>R : Symbol(R, Decl(dependentReturnType1.ts, 360, 27))
1013+
1014+
abstract perform(t: T): R;
1015+
>perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 360, 32))
1016+
>t : Symbol(t, Decl(dependentReturnType1.ts, 361, 21))
1017+
>T : Symbol(T, Decl(dependentReturnType1.ts, 360, 25))
1018+
>R : Symbol(R, Decl(dependentReturnType1.ts, 360, 27))
1019+
}
1020+
1021+
type ConditionalReturnType<T, R, EOp extends Operation<T, R> | undefined> =
1022+
>ConditionalReturnType : Symbol(ConditionalReturnType, Decl(dependentReturnType1.ts, 362, 1))
1023+
>T : Symbol(T, Decl(dependentReturnType1.ts, 364, 27))
1024+
>R : Symbol(R, Decl(dependentReturnType1.ts, 364, 29))
1025+
>EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 364, 32))
1026+
>Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 357, 1))
1027+
>T : Symbol(T, Decl(dependentReturnType1.ts, 364, 27))
1028+
>R : Symbol(R, Decl(dependentReturnType1.ts, 364, 29))
1029+
1030+
EOp extends Operation<T, R> ? R : EOp extends undefined ? T | R : T | R;
1031+
>EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 364, 32))
1032+
>Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 357, 1))
1033+
>T : Symbol(T, Decl(dependentReturnType1.ts, 364, 27))
1034+
>R : Symbol(R, Decl(dependentReturnType1.ts, 364, 29))
1035+
>R : Symbol(R, Decl(dependentReturnType1.ts, 364, 29))
1036+
>EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 364, 32))
1037+
>T : Symbol(T, Decl(dependentReturnType1.ts, 364, 27))
1038+
>R : Symbol(R, Decl(dependentReturnType1.ts, 364, 29))
1039+
>T : Symbol(T, Decl(dependentReturnType1.ts, 364, 27))
1040+
>R : Symbol(R, Decl(dependentReturnType1.ts, 364, 29))
1041+
1042+
class ConditionalOperation<T, R, EOp extends Operation<T, R> | undefined> extends Operation<T, ConditionalReturnType<T, R, EOp>> {
1043+
>ConditionalOperation : Symbol(ConditionalOperation, Decl(dependentReturnType1.ts, 365, 76))
1044+
>T : Symbol(T, Decl(dependentReturnType1.ts, 367, 27))
1045+
>R : Symbol(R, Decl(dependentReturnType1.ts, 367, 29))
1046+
>EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 367, 32))
1047+
>Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 357, 1))
1048+
>T : Symbol(T, Decl(dependentReturnType1.ts, 367, 27))
1049+
>R : Symbol(R, Decl(dependentReturnType1.ts, 367, 29))
1050+
>Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 357, 1))
1051+
>T : Symbol(T, Decl(dependentReturnType1.ts, 367, 27))
1052+
>ConditionalReturnType : Symbol(ConditionalReturnType, Decl(dependentReturnType1.ts, 362, 1))
1053+
>T : Symbol(T, Decl(dependentReturnType1.ts, 367, 27))
1054+
>R : Symbol(R, Decl(dependentReturnType1.ts, 367, 29))
1055+
>EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 367, 32))
1056+
1057+
constructor(
1058+
private predicate: (value: T) => boolean,
1059+
>predicate : Symbol(ConditionalOperation.predicate, Decl(dependentReturnType1.ts, 368, 16))
1060+
>value : Symbol(value, Decl(dependentReturnType1.ts, 369, 28))
1061+
>T : Symbol(T, Decl(dependentReturnType1.ts, 367, 27))
1062+
1063+
private thenOp: Operation<T, R>,
1064+
>thenOp : Symbol(ConditionalOperation.thenOp, Decl(dependentReturnType1.ts, 369, 49))
1065+
>Operation : Symbol(Operation, Decl(dependentReturnType1.ts, 357, 1))
1066+
>T : Symbol(T, Decl(dependentReturnType1.ts, 367, 27))
1067+
>R : Symbol(R, Decl(dependentReturnType1.ts, 367, 29))
1068+
1069+
private elseOp?: EOp
1070+
>elseOp : Symbol(ConditionalOperation.elseOp, Decl(dependentReturnType1.ts, 370, 40))
1071+
>EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 367, 32))
1072+
1073+
) {
1074+
super();
1075+
>super : Symbol(Operation, Decl(dependentReturnType1.ts, 357, 1))
1076+
}
1077+
1078+
perform(t: T): ConditionalReturnType<T, R, EOp> {
1079+
>perform : Symbol(ConditionalOperation.perform, Decl(dependentReturnType1.ts, 374, 5))
1080+
>t : Symbol(t, Decl(dependentReturnType1.ts, 376, 12))
1081+
>T : Symbol(T, Decl(dependentReturnType1.ts, 367, 27))
1082+
>ConditionalReturnType : Symbol(ConditionalReturnType, Decl(dependentReturnType1.ts, 362, 1))
1083+
>T : Symbol(T, Decl(dependentReturnType1.ts, 367, 27))
1084+
>R : Symbol(R, Decl(dependentReturnType1.ts, 367, 29))
1085+
>EOp : Symbol(EOp, Decl(dependentReturnType1.ts, 367, 32))
1086+
1087+
if (this.predicate(t)) {
1088+
>this.predicate : Symbol(ConditionalOperation.predicate, Decl(dependentReturnType1.ts, 368, 16))
1089+
>this : Symbol(ConditionalOperation, Decl(dependentReturnType1.ts, 365, 76))
1090+
>predicate : Symbol(ConditionalOperation.predicate, Decl(dependentReturnType1.ts, 368, 16))
1091+
>t : Symbol(t, Decl(dependentReturnType1.ts, 376, 12))
1092+
1093+
return this.thenOp.perform(t); // Bad: this is assignable to all of the branches of the conditional, but we still can't return it
1094+
>this.thenOp.perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 360, 32))
1095+
>this.thenOp : Symbol(ConditionalOperation.thenOp, Decl(dependentReturnType1.ts, 369, 49))
1096+
>this : Symbol(ConditionalOperation, Decl(dependentReturnType1.ts, 365, 76))
1097+
>thenOp : Symbol(ConditionalOperation.thenOp, Decl(dependentReturnType1.ts, 369, 49))
1098+
>perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 360, 32))
1099+
>t : Symbol(t, Decl(dependentReturnType1.ts, 376, 12))
1100+
1101+
} else if (typeof this.elseOp !== 'undefined') {
1102+
>this.elseOp : Symbol(ConditionalOperation.elseOp, Decl(dependentReturnType1.ts, 370, 40))
1103+
>this : Symbol(ConditionalOperation, Decl(dependentReturnType1.ts, 365, 76))
1104+
>elseOp : Symbol(ConditionalOperation.elseOp, Decl(dependentReturnType1.ts, 370, 40))
1105+
1106+
return this.elseOp.perform(t); // Ok
1107+
>this.elseOp.perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 360, 32))
1108+
>this.elseOp : Symbol(ConditionalOperation.elseOp, Decl(dependentReturnType1.ts, 370, 40))
1109+
>this : Symbol(ConditionalOperation, Decl(dependentReturnType1.ts, 365, 76))
1110+
>elseOp : Symbol(ConditionalOperation.elseOp, Decl(dependentReturnType1.ts, 370, 40))
1111+
>perform : Symbol(Operation.perform, Decl(dependentReturnType1.ts, 360, 32))
1112+
>t : Symbol(t, Decl(dependentReturnType1.ts, 376, 12))
1113+
1114+
} else {
1115+
return t; // Ok
1116+
>t : Symbol(t, Decl(dependentReturnType1.ts, 376, 12))
1117+
}
1118+
}
1119+
}
1120+
1121+
// Optional tuple element
1122+
function tupl<T extends true | false | undefined>(x: [string, some?: T]):
1123+
>tupl : Symbol(tupl, Decl(dependentReturnType1.ts, 385, 1))
1124+
>T : Symbol(T, Decl(dependentReturnType1.ts, 388, 14))
1125+
>x : Symbol(x, Decl(dependentReturnType1.ts, 388, 50))
1126+
>T : Symbol(T, Decl(dependentReturnType1.ts, 388, 14))
1127+
1128+
T extends true ? 1 : T extends false | undefined ? 2 : 1 | 2 {
1129+
>T : Symbol(T, Decl(dependentReturnType1.ts, 388, 14))
1130+
>T : Symbol(T, Decl(dependentReturnType1.ts, 388, 14))
1131+
1132+
if (x[1]) {
1133+
>x : Symbol(x, Decl(dependentReturnType1.ts, 388, 50))
1134+
>1 : Symbol(1)
1135+
1136+
return 1;
1137+
}
1138+
return 2;
1139+
}

Diff for: tests/baselines/reference/dependentReturnType1.types

+102
Original file line numberDiff line numberDiff line change
@@ -991,3 +991,105 @@ function h<T extends 1 | 2>(x: T): T extends 1 ? number : T extends 2 ? string :
991991
return 0; // Ok
992992
>0 : 0
993993
}
994+
995+
// From #33912
996+
abstract class Operation<T, R> {
997+
>Operation : Operation<T, R>
998+
999+
abstract perform(t: T): R;
1000+
>perform : (t: T) => R
1001+
>t : T
1002+
}
1003+
1004+
type ConditionalReturnType<T, R, EOp extends Operation<T, R> | undefined> =
1005+
>ConditionalReturnType : ConditionalReturnType<T, R, EOp>
1006+
1007+
EOp extends Operation<T, R> ? R : EOp extends undefined ? T | R : T | R;
1008+
1009+
class ConditionalOperation<T, R, EOp extends Operation<T, R> | undefined> extends Operation<T, ConditionalReturnType<T, R, EOp>> {
1010+
>ConditionalOperation : ConditionalOperation<T, R, EOp>
1011+
>Operation : Operation<T, ConditionalReturnType<T, R, EOp>>
1012+
1013+
constructor(
1014+
private predicate: (value: T) => boolean,
1015+
>predicate : (value: T) => boolean
1016+
>value : T
1017+
1018+
private thenOp: Operation<T, R>,
1019+
>thenOp : Operation<T, R>
1020+
1021+
private elseOp?: EOp
1022+
>elseOp : EOp | undefined
1023+
1024+
) {
1025+
super();
1026+
>super() : void
1027+
>super : typeof Operation
1028+
}
1029+
1030+
perform(t: T): ConditionalReturnType<T, R, EOp> {
1031+
>perform : (t: T) => ConditionalReturnType<T, R, EOp>
1032+
>t : T
1033+
1034+
if (this.predicate(t)) {
1035+
>this.predicate(t) : boolean
1036+
>this.predicate : (value: T) => boolean
1037+
>this : this
1038+
>predicate : (value: T) => boolean
1039+
>t : T
1040+
1041+
return this.thenOp.perform(t); // Bad: this is assignable to all of the branches of the conditional, but we still can't return it
1042+
>this.thenOp.perform(t) : R
1043+
>this.thenOp.perform : (t: T) => R
1044+
>this.thenOp : Operation<T, R>
1045+
>this : this
1046+
>thenOp : Operation<T, R>
1047+
>perform : (t: T) => R
1048+
>t : T
1049+
1050+
} else if (typeof this.elseOp !== 'undefined') {
1051+
>typeof this.elseOp !== 'undefined' : boolean
1052+
>typeof this.elseOp : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
1053+
>this.elseOp : EOp | undefined
1054+
>this : this
1055+
>elseOp : EOp | undefined
1056+
>'undefined' : "undefined"
1057+
1058+
return this.elseOp.perform(t); // Ok
1059+
>this.elseOp.perform(t) : R
1060+
>this.elseOp.perform : (t: T) => R
1061+
>this.elseOp : Operation<T, R>
1062+
>this : this
1063+
>elseOp : Operation<T, R>
1064+
>perform : (t: T) => R
1065+
>t : T
1066+
1067+
} else {
1068+
return t; // Ok
1069+
>t : T
1070+
}
1071+
}
1072+
}
1073+
1074+
// Optional tuple element
1075+
function tupl<T extends true | false | undefined>(x: [string, some?: T]):
1076+
>tupl : <T extends boolean | undefined>(x: [string, some?: T]) => T extends true ? 1 : T extends false | undefined ? 2 : 1 | 2
1077+
>true : true
1078+
>false : false
1079+
>x : [string, some?: T | undefined]
1080+
1081+
T extends true ? 1 : T extends false | undefined ? 2 : 1 | 2 {
1082+
>true : true
1083+
>false : false
1084+
1085+
if (x[1]) {
1086+
>x[1] : T | undefined
1087+
>x : [string, some?: T | undefined]
1088+
>1 : 1
1089+
1090+
return 1;
1091+
>1 : 1
1092+
}
1093+
return 2;
1094+
>2 : 2
1095+
}

Diff for: tests/cases/compiler/dependentReturnType1.ts

+37
Original file line numberDiff line numberDiff line change
@@ -358,4 +358,41 @@ function h<T extends 1 | 2>(x: T): T extends 1 ? number : T extends 2 ? string :
358358
return ""; // Ok
359359
}
360360
return 0; // Ok
361+
}
362+
363+
// From #33912
364+
abstract class Operation<T, R> {
365+
abstract perform(t: T): R;
366+
}
367+
368+
type ConditionalReturnType<T, R, EOp extends Operation<T, R> | undefined> =
369+
EOp extends Operation<T, R> ? R : EOp extends undefined ? T | R : T | R;
370+
371+
class ConditionalOperation<T, R, EOp extends Operation<T, R> | undefined> extends Operation<T, ConditionalReturnType<T, R, EOp>> {
372+
constructor(
373+
private predicate: (value: T) => boolean,
374+
private thenOp: Operation<T, R>,
375+
private elseOp?: EOp
376+
) {
377+
super();
378+
}
379+
380+
perform(t: T): ConditionalReturnType<T, R, EOp> {
381+
if (this.predicate(t)) {
382+
return this.thenOp.perform(t); // Bad: this is assignable to all of the branches of the conditional, but we still can't return it
383+
} else if (typeof this.elseOp !== 'undefined') {
384+
return this.elseOp.perform(t); // Ok
385+
} else {
386+
return t; // Ok
387+
}
388+
}
389+
}
390+
391+
// Optional tuple element
392+
function tupl<T extends true | false | undefined>(x: [string, some?: T]):
393+
T extends true ? 1 : T extends false | undefined ? 2 : 1 | 2 {
394+
if (x[1]) {
395+
return 1;
396+
}
397+
return 2;
361398
}

0 commit comments

Comments
 (0)