Skip to content

Commit 17173a6

Browse files
committed
Add test for split type/contextual type annotation
1 parent 32e75f7 commit 17173a6

File tree

1 file changed

+62
-16
lines changed

1 file changed

+62
-16
lines changed

tests/cases/compiler/recursion.ts

Lines changed: 62 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,47 @@
1-
let o = {
2-
p: 12,
3-
m(this: typeof o) {
4-
let x = this.m(); // x: number
5-
let y = this.p; // y: number
6-
return this.p;
1+
// TODO: Assignability error when the contextual type of data is `U & V`
2+
declare function create<U, V, W>(
3+
x: {data: U, methods: V, properties: W} as
4+
{
5+
data: U,
6+
methods: { [s: string]: (this: U & V & Propertise<W>, ...args: any[]) => any },
7+
properties: { [s: string]: (this: U & V & Propertise<W>, ...args: any[]) => any }
8+
}): U & V & Propertise<W>;
9+
let vue = create({
10+
data: { x: 1 },
11+
methods: {
12+
m() { return 12 /*this.x*/ },
13+
m2() { return this.m() },
14+
m3() { return this.p },
715
},
8-
m2() {
9-
return this.m() // this: any since it has no annotation
16+
properties: {
17+
p() { return 'foo' /*this.x*/ },
18+
p2() { return this.p },
19+
p3() { return this.m() },
1020
}
11-
}
21+
});
22+
/**
23+
Problem: you need to fix U and V but also make them provide a contextual type that includes the *whole* type.
24+
But transformed, so the *whole* *transformed* type.
25+
26+
So here's an idea: an in and out type. One is used for type inference (to)
27+
and the other is used for contextual typing. Plus maybe type inference from? Not sure about that one.
28+
*/
1229

13-
let x = o.m() // x: number
14-
let y = o.m2() // y: any
15-
let p = o.p // p: number
1630

1731
type Propertise<T> = { [K in keyof T]: return T[K] };
18-
type Vue<T extends { data, methods, properties }> = T['data'] & T['methods'] & Propertise<T['properties']>;
32+
type ExplicitVue<T extends { data, methods, properties }> = T['data'] & T['methods'] & Propertise<T['properties']>;
1933

2034
let options = {
2135
data: {
2236
a: 12,
2337
},
2438
methods: {
25-
m1(this: Vue<typeof options>) {
39+
m1(this: ExplicitVue<typeof options>) {
2640
this.a;
2741
this.m2();
2842
return this.a + this.p.length;
2943
},
30-
m2(this: Vue<typeof options>) {
44+
m2(this: ExplicitVue<typeof options>) {
3145
return this.m1();
3246
}
3347
},
@@ -36,4 +50,36 @@ let options = {
3650
}
3751
}
3852

39-
let app: Vue<typeof options>;
53+
let app: ExplicitVue<typeof options>;
54+
/*interface Vue<T> {
55+
data: any,
56+
methods: { [s: string]: (this: ExplicitVue, ...args: any[]) => any },
57+
properties: Propertise<{ [s: string]: (this: ExplicitVue, ...args: any[]) => any }>
58+
}
59+
declare function create<T>(options: Vue<T>): Vue<T>;
60+
create({
61+
data: { a: 12 },
62+
methods: {
63+
},
64+
properties: {
65+
}
66+
});
67+
*/
68+
/*
69+
let o = {
70+
p: 12,
71+
m(this: typeof o) {
72+
let x = this.m(); // x: number
73+
let y = this.p; // y: number
74+
return this.p;
75+
},
76+
m2() {
77+
return this.m() // this: any since it has no annotation
78+
}
79+
}
80+
81+
let x = o.m() // x: number
82+
let y = o.m2() // y: any
83+
let p = o.p // p: number
84+
85+
*/

0 commit comments

Comments
 (0)