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 } ,
7
15
} ,
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 ( ) } ,
10
20
}
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
+ */
12
29
13
- let x = o . m ( ) // x: number
14
- let y = o . m2 ( ) // y: any
15
- let p = o . p // p: number
16
30
17
31
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' ] > ;
19
33
20
34
let options = {
21
35
data : {
22
36
a : 12 ,
23
37
} ,
24
38
methods : {
25
- m1 ( this : Vue < typeof options > ) {
39
+ m1 ( this : ExplicitVue < typeof options > ) {
26
40
this . a ;
27
41
this . m2 ( ) ;
28
42
return this . a + this . p . length ;
29
43
} ,
30
- m2 ( this : Vue < typeof options > ) {
44
+ m2 ( this : ExplicitVue < typeof options > ) {
31
45
return this . m1 ( ) ;
32
46
}
33
47
} ,
@@ -36,4 +50,36 @@ let options = {
36
50
}
37
51
}
38
52
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