Skip to content

Commit eaf2abc

Browse files
committed
Add many more tests showing current behaviors
1 parent 6fb95e8 commit eaf2abc

File tree

4 files changed

+1008
-41
lines changed

4 files changed

+1008
-41
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,148 @@
11
//// [indexAccessCombinedInference.ts]
2+
// Simple case
23
interface Args {
34
TA: object,
45
TY: object
56
}
67

7-
function foo<T extends Args>(
8+
declare function foo<T extends Args>(
89
a: T["TA"],
9-
b: T["TY"]): T["TA"] & T["TY"] {
10-
return undefined!;
11-
}
10+
b: T["TY"]): T["TA"] & T["TY"];
1211

1312
const x = foo({
1413
x: {
1514
j: 12,
1615
i: 11
1716
}
18-
}, { y: 42 });
17+
}, { y: 42 });
18+
19+
// Union result type
20+
interface A {
21+
foo: number;
22+
}
23+
interface B {
24+
bar: string;
25+
}
26+
declare const something: A | B;
27+
28+
const y = foo(something, { bat: 42 });
29+
30+
// Union key type
31+
interface Args2 {
32+
TA?: object, // Optional since only one of TA or TB needs to be infered in the below argument list
33+
TB?: object,
34+
TY: object
35+
}
36+
declare function foo2<T extends Args2>(
37+
a: T["TA"] | T["TB"],
38+
b: T["TY"]): {a: T["TA"], b: T["TB"]} & T["TY"];
39+
declare function foo3<T extends Args2>( // Morally equivalent to foo2
40+
a: T["TA" | "TB"],
41+
b: T["TY"]): {a: T["TA"], b: T["TB"]} & T["TY"];
42+
let z = foo2({
43+
x: {
44+
j: 12,
45+
i: 11
46+
}
47+
}, { y: 42 });
48+
let zz = foo3({
49+
x: {
50+
j: 12,
51+
i: 11
52+
}
53+
}, { y: 42 });
54+
z = zz;
55+
zz = z;
56+
57+
// Higher-order
58+
interface Args3 {
59+
Key: "A" | "B",
60+
A: object,
61+
B: object,
62+
Merge: object,
63+
}
64+
declare const either: "A" | "B";
65+
declare function pickOne<T extends Args3>(key: T["Key"], left: T["A"], right: T["B"], into: T["Merge"]): T[T["Key"]] & T["Merge"];
66+
67+
const opt1 = pickOne("A", {x: 12}, {y: ""}, {z: /./});
68+
const opt2 = pickOne("B", {x: 12}, {y: ""}, {z: /./});
69+
const opt3 = pickOne(either, {x: 12}, {y: ""}, {z: /./});
70+
71+
const pickDelayed = <TKey extends Args3["Key"]>(x: TKey) => pickOne(x, {j: x}, {i: x}, {chosen: x});
72+
const opt4 = pickDelayed("A");
73+
const opt5 = pickDelayed("B");
74+
const opt6 = pickDelayed(either);
75+
76+
// Reopenable
77+
interface Args3 {
78+
/**
79+
* One must make patched parameters optional, otherwise signatures expecting the unpatched
80+
* interface (ie, pickOne above) will not be able to produce a type satisfying the interface
81+
* (as there are no inference sites for the new members) and will fall back to the constraints on each member
82+
*/
83+
Extra?: object,
84+
}
85+
declare function pickOne<T extends Args3>(key: T["Key"], left: T["A"], right: T["B"], into: T["Merge"], extra: T["Extra"]): T[T["Key"]] & {into: T["Merge"], extra: T["Extra"]};
86+
const opt7 = pickOne("A", {x: 12}, {y: ""}, {z: /./}, {z: /./});
87+
const opt8 = pickOne("B", {x: 12}, {y: ""}, {z: /./}, {z: /./});
88+
const opt9 = pickOne(either, {x: 12}, {y: ""}, {z: /./}, {z: /./});
89+
90+
// Interactions with `this` types
91+
interface TPicker {
92+
Key: keyof this,
93+
X: number,
94+
Y: string
95+
}
96+
declare function chooseLiteral<T extends TPicker>(choice: T["Key"], x: T["X"], y:T["Y"]): T[T["Key"]];
97+
const cx = chooseLiteral("X", 1, "no");
98+
const cy = chooseLiteral("Y", 0, "yes");
99+
const ceither = chooseLiteral("X" as "X" | "Y", 1, "yes");
100+
const cneither = chooseLiteral("Key", 0, "no");
101+
102+
// Multiple inference sites
103+
interface Args4 {
104+
0: object,
105+
1: Record<keyof this["0"], Function>,
106+
}
107+
declare function dualInputs<T extends Args4>(x: T["0"], y: T["0"], toDelay: T["1"]): T["0"] & {transformers: T["1"]};
108+
109+
const result = dualInputs({x: 0}, {x: 1}, {x: () => ""});
110+
19111

20112
//// [indexAccessCombinedInference.js]
21-
function foo(a, b) {
22-
return undefined;
23-
}
24113
var x = foo({
25114
x: {
26115
j: 12,
27116
i: 11
28117
}
29118
}, { y: 42 });
119+
var y = foo(something, { bat: 42 });
120+
var z = foo2({
121+
x: {
122+
j: 12,
123+
i: 11
124+
}
125+
}, { y: 42 });
126+
var zz = foo3({
127+
x: {
128+
j: 12,
129+
i: 11
130+
}
131+
}, { y: 42 });
132+
z = zz;
133+
zz = z;
134+
var opt1 = pickOne("A", { x: 12 }, { y: "" }, { z: /./ });
135+
var opt2 = pickOne("B", { x: 12 }, { y: "" }, { z: /./ });
136+
var opt3 = pickOne(either, { x: 12 }, { y: "" }, { z: /./ });
137+
var pickDelayed = function (x) { return pickOne(x, { j: x }, { i: x }, { chosen: x }); };
138+
var opt4 = pickDelayed("A");
139+
var opt5 = pickDelayed("B");
140+
var opt6 = pickDelayed(either);
141+
var opt7 = pickOne("A", { x: 12 }, { y: "" }, { z: /./ }, { z: /./ });
142+
var opt8 = pickOne("B", { x: 12 }, { y: "" }, { z: /./ }, { z: /./ });
143+
var opt9 = pickOne(either, { x: 12 }, { y: "" }, { z: /./ }, { z: /./ });
144+
var cx = chooseLiteral("X", 1, "no");
145+
var cy = chooseLiteral("Y", 0, "yes");
146+
var ceither = chooseLiteral("X", 1, "yes");
147+
var cneither = chooseLiteral("Key", 0, "no");
148+
var result = dualInputs({ x: 0 }, { x: 1 }, { x: function () { return ""; } });

0 commit comments

Comments
 (0)