1
- import { Vue , CreateElement } from "./vue" ;
1
+ import { Vue , CreateElement , CombinedVueInstance } from "./vue" ;
2
2
import { VNode , VNodeData , VNodeDirective } from "./vnode" ;
3
3
4
4
type Constructor = {
5
5
new ( ...args : any [ ] ) : any ;
6
6
}
7
7
8
- export type Component = typeof Vue | ComponentOptions < Vue > | FunctionalComponentOptions ;
8
+ // we don't support infer props in async component
9
+ export type Component < Data = DefaultData < Vue > , Methods = DefaultMethods < Vue > , Computed = DefaultComputed , Props = DefaultProps > =
10
+ | typeof Vue
11
+ | FunctionalComponentOptions < Props >
12
+ | ThisTypedComponentOptionsWithArrayProps < Vue , Data , Methods , Computed , keyof Props >
13
+ | ThisTypedComponentOptionsWithRecordProps < Vue , Data , Methods , Computed , Props > ;
9
14
10
15
interface EsModuleComponent {
11
16
default : Component
12
17
}
13
18
14
- export type AsyncComponent = (
15
- resolve : ( component : Component ) => void ,
19
+ export type AsyncComponent < Data = DefaultData < Vue > , Methods = DefaultMethods < Vue > , Computed = DefaultComputed , Props = DefaultProps > = (
20
+ resolve : ( component : Component < Data , Methods , Computed , Props > ) => void ,
16
21
reject : ( reason ?: any ) => void
17
- ) => Promise < Component | EsModuleComponent > | Component | void ;
22
+ ) => Promise < Component | EsModuleComponent > | void ;
23
+
24
+ /**
25
+ * When the `Computed` type parameter on `ComponentOptions` is inferred,
26
+ * it should have a property with the return type of every get-accessor.
27
+ * Since there isn't a way to query for the return type of a function, we allow TypeScript
28
+ * to infer from the shape of `Accessors<Computed>` and work backwards.
29
+ */
30
+ export type Accessors < T > = {
31
+ [ K in keyof T ] : ( ( ) => T [ K ] ) | ComputedOptions < T [ K ] >
32
+ }
18
33
19
- export interface ComponentOptions < V extends Vue > {
20
- data ?: Object | ( ( this : V ) => Object ) ;
21
- props ?: string [ ] | { [ key : string ] : PropOptions | Constructor | Constructor [ ] } ;
34
+ /**
35
+ * This type should be used when an array of strings is used for a component's `props` value.
36
+ */
37
+ export type ThisTypedComponentOptionsWithArrayProps < V extends Vue , Data , Methods , Computed , PropNames extends string > =
38
+ object &
39
+ ComponentOptions < V , Data | ( ( this : Readonly < Record < PropNames , any > > & V ) => Data ) , Methods , Computed , PropNames [ ] > &
40
+ ThisType < CombinedVueInstance < V , Data , Methods , Computed , Readonly < Record < PropNames , any > > > > ;
41
+
42
+ /**
43
+ * This type should be used when an object mapped to `PropOptions` is used for a component's `props` value.
44
+ */
45
+ export type ThisTypedComponentOptionsWithRecordProps < V extends Vue , Data , Methods , Computed , Props > =
46
+ object &
47
+ ComponentOptions < V , Data | ( ( this : Readonly < Props > & V ) => Data ) , Methods , Computed , RecordPropsDefinition < Props > > &
48
+ ThisType < CombinedVueInstance < V , Data , Methods , Computed , Readonly < Props > > > ;
49
+
50
+ type DefaultData < V > = object | ( ( this : V ) => object ) ;
51
+ type DefaultProps = Record < string , any > ;
52
+ type DefaultMethods < V > = { [ key : string ] : ( this : V , ...args : any [ ] ) => any } ;
53
+ type DefaultComputed = { [ key : string ] : any } ;
54
+ export interface ComponentOptions <
55
+ V extends Vue ,
56
+ Data = DefaultData < V > ,
57
+ Methods = DefaultMethods < V > ,
58
+ Computed = DefaultComputed ,
59
+ PropsDef = PropsDefinition < DefaultProps > > {
60
+ data ?: Data ;
61
+ props ?: PropsDef ;
22
62
propsData ?: Object ;
23
- computed ?: { [ key : string ] : ( ( this : V ) => any ) | ComputedOptions < V > } ;
24
- methods ?: { [ key : string ] : ( this : V , ... args : any [ ] ) => any } ;
25
- watch ?: { [ key : string ] : ( { handler : WatchHandler < V , any > } & WatchOptions ) | WatchHandler < V , any > | string } ;
63
+ computed ?: Accessors < Computed > ;
64
+ methods ?: Methods ;
65
+ watch ?: Record < string , WatchOptionsWithHandler < any > | WatchHandler < any > | string > ;
26
66
27
67
el ?: Element | String ;
28
68
template ?: string ;
29
- render ?( this : V , createElement : CreateElement ) : VNode ;
69
+ render ?( createElement : CreateElement ) : VNode ;
30
70
renderError ?: ( h : ( ) => VNode , err : Error ) => VNode ;
31
71
staticRenderFns ?: ( ( createElement : CreateElement ) => VNode ) [ ] ;
32
72
33
73
beforeCreate ?( this : V ) : void ;
34
- created ?( this : V ) : void ;
35
- beforeDestroy ?( this : V ) : void ;
36
- destroyed ?( this : V ) : void ;
37
- beforeMount ?( this : V ) : void ;
38
- mounted ?( this : V ) : void ;
39
- beforeUpdate ?( this : V ) : void ;
40
- updated ?( this : V ) : void ;
41
- activated ?( this : V ) : void ;
42
- deactivated ?( this : V ) : void ;
43
-
44
- directives ?: { [ key : string ] : DirectiveOptions | DirectiveFunction } ;
45
- components ?: { [ key : string ] : Component | AsyncComponent } ;
74
+ created ?( ) : void ;
75
+ beforeDestroy ?( ) : void ;
76
+ destroyed ?( ) : void ;
77
+ beforeMount ?( ) : void ;
78
+ mounted ?( ) : void ;
79
+ beforeUpdate ?( ) : void ;
80
+ updated ?( ) : void ;
81
+ activated ?( ) : void ;
82
+ deactivated ?( ) : void ;
83
+
84
+ directives ?: { [ key : string ] : DirectiveFunction | DirectiveOptions } ;
85
+ components ?: { [ key : string ] : Component < any , any , any , any > | AsyncComponent < any , any , any , any > } ;
46
86
transitions ?: { [ key : string ] : Object } ;
47
87
filters ?: { [ key : string ] : Function } ;
48
88
@@ -57,49 +97,64 @@ export interface ComponentOptions<V extends Vue> {
57
97
parent ?: Vue ;
58
98
mixins ?: ( ComponentOptions < Vue > | typeof Vue ) [ ] ;
59
99
name ?: string ;
100
+ // TODO: support properly inferred 'extends'
60
101
extends ?: ComponentOptions < Vue > | typeof Vue ;
61
102
delimiters ?: [ string , string ] ;
62
103
comments ?: boolean ;
63
104
inheritAttrs ?: boolean ;
64
105
}
65
106
66
- export interface FunctionalComponentOptions {
107
+ export interface FunctionalComponentOptions < Props = DefaultProps , PropDefs = PropsDefinition < Props > > {
67
108
name ?: string ;
68
- props ?: string [ ] | { [ key : string ] : PropOptions | Constructor | Constructor [ ] } ;
109
+ props ?: PropDefs ;
69
110
inject ?: { [ key : string ] : string | symbol } | string [ ] ;
70
111
functional : boolean ;
71
- render ( this : never , createElement : CreateElement , context : RenderContext ) : VNode | void ;
112
+ render ( this : undefined , createElement : CreateElement , context : RenderContext < Props > ) : VNode ;
72
113
}
73
114
74
- export interface RenderContext {
75
- props : any ;
115
+ export interface RenderContext < Props = DefaultProps > {
116
+ props : Props ;
76
117
children : VNode [ ] ;
77
118
slots ( ) : any ;
78
119
data : VNodeData ;
79
120
parent : Vue ;
80
121
injections : any
81
122
}
82
123
83
- export interface PropOptions {
84
- type ?: Constructor | Constructor [ ] | null ;
124
+ export type Prop < T > = { ( ) : T } | { new ( ...args : any [ ] ) : T & object }
125
+
126
+ export type PropValidator < T > = PropOptions < T > | Prop < T > | Prop < T > [ ] ;
127
+
128
+ export interface PropOptions < T = any > {
129
+ type ?: Prop < T > | Prop < T > [ ] ;
85
130
required ?: boolean ;
86
- default ?: any ;
87
- validator ?( value : any ) : boolean ;
131
+ default ?: T | null | undefined | ( ( ) => object ) ;
132
+ validator ?( value : T ) : boolean ;
88
133
}
89
134
90
- export interface ComputedOptions < V > {
91
- get ?( this : V ) : any ;
92
- set ?( this : V , value : any ) : void ;
135
+ export type RecordPropsDefinition < T > = {
136
+ [ K in keyof T ] : PropValidator < T [ K ] >
137
+ }
138
+ export type ArrayPropsDefinition < T > = ( keyof T ) [ ] ;
139
+ export type PropsDefinition < T > = ArrayPropsDefinition < T > | RecordPropsDefinition < T > ;
140
+
141
+ export interface ComputedOptions < T > {
142
+ get ?( ) : T ;
143
+ set ?( value : T ) : void ;
93
144
cache ?: boolean ;
94
145
}
95
146
96
- export type WatchHandler < V , T > = ( this : V , val : T , oldVal : T ) => void ;
147
+ export type WatchHandler < T > = ( val : T , oldVal : T ) => void ;
97
148
98
149
export interface WatchOptions {
99
150
deep ?: boolean ;
100
151
immediate ?: boolean ;
101
152
}
102
153
154
+ export interface WatchOptionsWithHandler < T > extends WatchOptions {
155
+ handler : WatchHandler < T > ;
156
+ }
157
+
103
158
export type DirectiveFunction = (
104
159
el : HTMLElement ,
105
160
binding : VNodeDirective ,
0 commit comments