Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit db138e2

Browse filesBrowse files
HerringtonDarkholmeyyx990803
authored andcommitted
feat(types): further improve Vue type declarations for canonical usage (#6391)
1 parent 64e3943 commit db138e2
Copy full SHA for db138e2

10 files changed

+394
-157
lines changed

‎package.json

Copy file name to clipboardExpand all lines: package.json
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@
7979
"eslint": "^3.0.0",
8080
"eslint-loader": "^1.7.1",
8181
"eslint-plugin-flowtype": "^2.34.0",
82-
"eslint-plugin-jasmine": "^2.2.0",
82+
"eslint-plugin-jasmine": "^2.8.4",
8383
"eslint-plugin-vue-libs": "^1.2.0",
8484
"file-loader": "^0.11.2",
8585
"flow-bin": "^0.54.0",
@@ -119,7 +119,7 @@
119119
"selenium-server": "^2.53.1",
120120
"serialize-javascript": "^1.3.0",
121121
"shelljs": "^0.7.8",
122-
"typescript": "^2.3.4",
122+
"typescript": "^2.5.2",
123123
"uglify-js": "^3.0.15",
124124
"webpack": "^2.6.1",
125125
"weex-js-runtime": "^0.22.0"

‎types/index.d.ts

Copy file name to clipboard
+31-32Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,36 @@
1-
import * as V from "./vue";
2-
import * as Options from "./options";
3-
import * as Plugin from "./plugin";
4-
import * as VNode from "./vnode";
1+
import { Vue } from "./vue";
52

6-
// `Vue` in `export = Vue` must be a namespace
7-
// All available types are exported via this namespace
8-
declare namespace Vue {
9-
export type CreateElement = V.CreateElement;
3+
export default Vue;
104

11-
export type Component = Options.Component;
12-
export type AsyncComponent = Options.AsyncComponent;
13-
export type ComponentOptions<V extends Vue> = Options.ComponentOptions<V>;
14-
export type FunctionalComponentOptions = Options.FunctionalComponentOptions;
15-
export type RenderContext = Options.RenderContext;
16-
export type PropOptions = Options.PropOptions;
17-
export type ComputedOptions<V extends Vue> = Options.ComputedOptions<V>;
18-
export type WatchHandler<V extends Vue> = Options.WatchHandler<V, any>;
19-
export type WatchOptions = Options.WatchOptions;
20-
export type DirectiveFunction = Options.DirectiveFunction;
21-
export type DirectiveOptions = Options.DirectiveOptions;
5+
export {
6+
CreateElement
7+
} from "./vue";
228

23-
export type PluginFunction<T> = Plugin.PluginFunction<T>;
24-
export type PluginObject<T> = Plugin.PluginObject<T>;
9+
export {
10+
Component,
11+
AsyncComponent,
12+
ComponentOptions,
13+
FunctionalComponentOptions,
14+
RenderContext,
15+
PropOptions,
16+
ComputedOptions,
17+
WatchHandler,
18+
WatchOptions,
19+
WatchOptionsWithHandler,
20+
DirectiveFunction,
21+
DirectiveOptions
22+
} from "./options";
2523

26-
export type VNodeChildren = VNode.VNodeChildren;
27-
export type VNodeChildrenArrayContents = VNode.VNodeChildrenArrayContents;
28-
export type VNode = VNode.VNode;
29-
export type VNodeComponentOptions = VNode.VNodeComponentOptions;
30-
export type VNodeData = VNode.VNodeData;
31-
export type VNodeDirective = VNode.VNodeDirective;
32-
}
24+
export {
25+
PluginFunction,
26+
PluginObject
27+
} from "./plugin";
3328

34-
// TS cannot merge imported class with namespace, declare a subclass to bypass
35-
declare class Vue extends V.Vue {}
36-
37-
export = Vue;
29+
export {
30+
VNodeChildren,
31+
VNodeChildrenArrayContents,
32+
VNode,
33+
VNodeComponentOptions,
34+
VNodeData,
35+
VNodeDirective
36+
} from "./vnode";

‎types/options.d.ts

Copy file name to clipboardExpand all lines: types/options.d.ts
+92-37Lines changed: 92 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,88 @@
1-
import { Vue, CreateElement } from "./vue";
1+
import { Vue, CreateElement, CombinedVueInstance } from "./vue";
22
import { VNode, VNodeData, VNodeDirective } from "./vnode";
33

44
type Constructor = {
55
new (...args: any[]): any;
66
}
77

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>;
914

1015
interface EsModuleComponent {
1116
default: Component
1217
}
1318

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,
1621
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+
}
1833

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;
2262
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>;
2666

2767
el?: Element | String;
2868
template?: string;
29-
render?(this: V, createElement: CreateElement): VNode;
69+
render?(createElement: CreateElement): VNode;
3070
renderError?: (h: () => VNode, err: Error) => VNode;
3171
staticRenderFns?: ((createElement: CreateElement) => VNode)[];
3272

3373
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> };
4686
transitions?: { [key: string]: Object };
4787
filters?: { [key: string]: Function };
4888

@@ -57,49 +97,64 @@ export interface ComponentOptions<V extends Vue> {
5797
parent?: Vue;
5898
mixins?: (ComponentOptions<Vue> | typeof Vue)[];
5999
name?: string;
100+
// TODO: support properly inferred 'extends'
60101
extends?: ComponentOptions<Vue> | typeof Vue;
61102
delimiters?: [string, string];
62103
comments?: boolean;
63104
inheritAttrs?: boolean;
64105
}
65106

66-
export interface FunctionalComponentOptions {
107+
export interface FunctionalComponentOptions<Props = DefaultProps, PropDefs = PropsDefinition<Props>> {
67108
name?: string;
68-
props?: string[] | { [key: string]: PropOptions | Constructor | Constructor[] };
109+
props?: PropDefs;
69110
inject?: { [key: string]: string | symbol } | string[];
70111
functional: boolean;
71-
render(this: never, createElement: CreateElement, context: RenderContext): VNode | void;
112+
render(this: undefined, createElement: CreateElement, context: RenderContext<Props>): VNode;
72113
}
73114

74-
export interface RenderContext {
75-
props: any;
115+
export interface RenderContext<Props=DefaultProps> {
116+
props: Props;
76117
children: VNode[];
77118
slots(): any;
78119
data: VNodeData;
79120
parent: Vue;
80121
injections: any
81122
}
82123

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>[];
85130
required?: boolean;
86-
default?: any;
87-
validator?(value: any): boolean;
131+
default?: T | null | undefined | (() => object);
132+
validator?(value: T): boolean;
88133
}
89134

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;
93144
cache?: boolean;
94145
}
95146

96-
export type WatchHandler<V, T> = (this: V, val: T, oldVal: T) => void;
147+
export type WatchHandler<T> = (val: T, oldVal: T) => void;
97148

98149
export interface WatchOptions {
99150
deep?: boolean;
100151
immediate?: boolean;
101152
}
102153

154+
export interface WatchOptionsWithHandler<T> extends WatchOptions {
155+
handler: WatchHandler<T>;
156+
}
157+
103158
export type DirectiveFunction = (
104159
el: HTMLElement,
105160
binding: VNodeDirective,

‎types/test/augmentation-test.ts

Copy file name to clipboardExpand all lines: types/test/augmentation-test.ts
+16-5Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Vue = require("../index");
1+
import Vue from "../index";
22

33
declare module "../vue" {
44
// add instance property and method
@@ -8,9 +8,9 @@ declare module "../vue" {
88
}
99

1010
// add static property and method
11-
namespace Vue {
12-
const staticProperty: string;
13-
function staticMethod(): void;
11+
interface VueConstructor {
12+
staticProperty: string;
13+
staticMethod(): void;
1414
}
1515
}
1616

@@ -22,10 +22,21 @@ declare module "../options" {
2222
}
2323

2424
const vm = new Vue({
25+
props: ["bar"],
2526
data: {
2627
a: true
2728
},
28-
foo: "foo"
29+
foo: "foo",
30+
methods: {
31+
foo() {
32+
this.a = false;
33+
}
34+
},
35+
computed: {
36+
BAR(): string {
37+
return this.bar.toUpperCase();
38+
}
39+
}
2940
});
3041

3142
vm.$instanceProperty;

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.