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 ,