Repository: vuejs/vue
Pull request: Update typings

### Update methods option type

Apply `this` type in the functions of `methods` option like lifecycle hooks. (`Function` is alias of `(...args: any[]) => any`)
We can omit `this` type annotation for methods option due to this update (See options-test.ts).
### Improve $createElement type and expose it
1. Allow to create empty vnode (`h()`).
2. Allow to pass vnode children to 2nd argument.

Also, this patch enable us to use the type of `$createElement`. It would be useful when we annotate render option type manually.

``` js
import { CreateElement } from 'vue'

export default {
  render (h: CreateElement) {
    // ...
  }
}
```


Changed files:
filename: types/index.d.ts
patch: @@ -1,11 +1,13 @@
-import {Vue as _Vue} from "./vue";
+import * as V from "./vue";
 import * as Options from "./options";
 import * as Plugin from "./plugin";
 import * as VNode from "./vnode";
 
 // `Vue` in `export = Vue` must be a namespace
 // All available types are exported via this namespace
 declare namespace Vue {
+  export type CreateElement = V.CreateElement;
+
   export type Component = Options.Component;
   export type AsyncComponent = Options.AsyncComponent;
   export type ComponentOptions<V extends Vue> = Options.ComponentOptions<V>;
@@ -30,6 +32,6 @@ declare namespace Vue {
 }
 
 // TS cannot merge imported class with namespace, declare a subclass to bypass
-declare class Vue extends _Vue {}
+declare class Vue extends V.Vue {}
 
 export = Vue;

filename: types/options.d.ts
patch: @@ -1,12 +1,10 @@
-import { Vue } from "./vue";
+import { Vue, CreateElement } from "./vue";
 import { VNode, VNodeData, VNodeDirective } from "./vnode";
 
 type Constructor = {
   new (...args: any[]): any;
 }
 
-type $createElement = typeof Vue.prototype.$createElement;
-
 export type Component = typeof Vue | ComponentOptions<Vue> | FunctionalComponentOptions;
 export type AsyncComponent = (
   resolve: (component: Component) => void,
@@ -18,13 +16,13 @@ export interface ComponentOptions<V extends Vue> {
   props?: string[] | { [key: string]: PropOptions | Constructor | Constructor[] };
   propsData?: Object;
   computed?: { [key: string]: ((this: V) => any) | ComputedOptions<V> };
-  methods?: { [key: string]: Function };
+  methods?: { [key: string]: (this: V, ...args: any[]) => any };
   watch?: { [key: string]: ({ handler: WatchHandler<V> } & WatchOptions) | WatchHandler<V> | string };
 
   el?: Element | String;
   template?: string;
-  render?(this: V, createElement: $createElement): VNode;
-  staticRenderFns?: ((createElement: $createElement) => VNode)[];
+  render?(this: V, createElement: CreateElement): VNode;
+  staticRenderFns?: ((createElement: CreateElement) => VNode)[];
 
   beforeCreate?(this: V): void;
   created?(this: V): void;
@@ -50,7 +48,7 @@ export interface ComponentOptions<V extends Vue> {
 export interface FunctionalComponentOptions {
   props?: string[] | { [key: string]: PropOptions | Constructor | Constructor[] };
   functional: boolean;
-  render(this: never, createElement: $createElement, context: RenderContext): VNode;
+  render(this: never, createElement: CreateElement, context: RenderContext): VNode;
   name?: string;
 }
 

filename: types/test/options-test.ts
patch: @@ -42,7 +42,7 @@ Vue.component('component', {
     }
   },
   methods: {
-    plus(this: Component) {
+    plus() {
       this.a++;
     }
   },
@@ -88,7 +88,8 @@ Vue.component('component', {
       key: 'myKey',
       ref: 'myRef'
     }, [
-      createElement("div", {}, "message"),
+      createElement(),
+      createElement("div", "message"),
       createElement(Vue.component("component")),
       createElement({} as ComponentOptions<Vue>),
       createElement({ functional: true }),
@@ -107,7 +108,7 @@ Vue.component('component', {
 
       "message",
 
-      [createElement("div", {}, "message")]
+      [createElement("div", "message")]
     ]);
   },
   staticRenderFns: [],

filename: types/vue.d.ts
patch: @@ -11,6 +11,23 @@ import {
 import { VNode, VNodeData, VNodeChildren } from "./vnode";
 import { PluginFunction, PluginObject } from "./plugin";
 
+export type CreateElement = {
+  // empty node
+  (): VNode;
+
+  // element or component name
+  (tag: string, children: VNodeChildren): VNode;
+  (tag: string, data?: VNodeData, children?: VNodeChildren): VNode;
+
+  // component constructor or options
+  (tag: Component, children: VNodeChildren): VNode;
+  (tag: Component, data?: VNodeData, children?: VNodeChildren): VNode;
+
+  // async component
+  (tag: AsyncComponent, children: VNodeChildren): VNode;
+  (tag: AsyncComponent, data?: VNodeData, children?: VNodeChildren): VNode;
+}
+
 export declare class Vue {
 
   constructor(options?: ComponentOptions<Vue>);
@@ -40,12 +57,7 @@ export declare class Vue {
   $off(event?: string, callback?: Function): this;
   $emit(event: string, ...args: any[]): this;
   $nextTick(callback?: (this: this) => void): void;
-  $createElement(
-    tag?: string | Component | AsyncComponent,
-    data?: VNodeData,
-    children?: VNodeChildren
-  ): VNode;
-
+  $createElement: CreateElement;
 
   static config: {
     silent: boolean;