Repository: vuejs/vue
Pull request: Fix definitons

- add “FunctionalComponentOptions” and “ContextObject”
- fix and update types
#3509 and #3582


Changed files:
filename: types/options.d.ts
patch: @@ -1,10 +1,12 @@
 import { Vue } from "./vue.d";
-import { VNode, VNodeDirective } from "./vnode.d";
+import { VNode, VNodeData, VNodeDirective } from "./vnode.d";
 
 type Constructor = {
   new (...args: any[]): any;
 }
 
+type $createElement = typeof Vue.prototype.$createElement;
+
 export interface ComponentOptions {
   data?: Object | ( (this: Vue) => Object );
   props?: string[] | { [key: string]: PropOptions | Constructor | Constructor[] };
@@ -15,7 +17,7 @@ export interface ComponentOptions {
 
   el?: Element | String;
   template?: string;
-  render?(createElement: typeof Vue.prototype.$createElement): VNode;
+  render?(createElement: $createElement): VNode;
   staticRenderFns?: (() => VNode)[];
 
   beforeCreate?(): void;
@@ -28,7 +30,7 @@ export interface ComponentOptions {
   updated?(): void;
 
   directives?: { [key: string]: DirectiveOptions | DirectiveFunction };
-  components?: { [key: string]: ComponentOptions | typeof Vue };
+  components?: { [key: string]: ComponentOptions | FunctionalComponentOptions | typeof Vue };
   transitions?: { [key: string]: Object };
   filters?: { [key: string]: Function };
 
@@ -39,6 +41,21 @@ export interface ComponentOptions {
   delimiters?: [string, string];
 }
 
+export interface FunctionalComponentOptions {
+  props?: string[] | { [key: string]: PropOptions | Constructor | Constructor[] };
+  functional: boolean;
+  render(this: never, createElement: $createElement, context: RenderContext): VNode;
+  name?: string;
+}
+
+export interface RenderContext {
+  props: any;
+  children: VNode[];
+  slots: any;
+  data: VNodeData;
+  parent: Vue;
+}
+
 export interface PropOptions {
   type?: Constructor | Constructor[] | null;
   required?: boolean;

filename: types/test/options-test.ts
patch: @@ -1,11 +1,12 @@
 import Vue = require("../index.d");
 import { ComponentOptions } from "../options.d";
+import { FunctionalComponentOptions } from "../options.d";
 
 interface Component extends Vue {
   a: number;
 }
 
-const Options: ComponentOptions = {
+Vue.component('component', {
   data() {
     return {
       a: 1
@@ -133,4 +134,17 @@ const Options: ComponentOptions = {
   name: "Component",
   extends: {} as ComponentOptions,
   delimiters: ["${", "}"]
-}
+} as ComponentOptions);
+
+Vue.component('functional-component', {
+  props: ['prop'],
+  functional: true,
+  render(createElement, context) {
+    context.props;
+    context.children;
+    context.slots;
+    context.data;
+    context.parent;
+    return createElement("div", {}, context.children);
+  }
+} as FunctionalComponentOptions);

filename: types/vue.d.ts
patch: @@ -1,5 +1,6 @@
 import {
   ComponentOptions,
+  FunctionalComponentOptions,
   WatchOptions,
   WatchHandler,
   DirectiveOptions,
@@ -59,11 +60,20 @@ export declare class Vue {
   static set<T>(array: T[], key: number, value: T): T;
   static delete(object: Object, key: string): void;
 
-  static directive(id: string, definition?: DirectiveOptions | DirectiveFunction): DirectiveOptions;
+  static directive(
+    id: string,
+    definition?: DirectiveOptions | DirectiveFunction
+  ): DirectiveOptions;
   static filter(id: string, definition?: Function): Function;
-  static component(id: string, definition?: ComponentOptions | typeof Vue): typeof Vue;
+  static component(
+    id: string,
+    definition?: ComponentOptions | FunctionalComponentOptions | typeof Vue
+  ): typeof Vue;
 
   static use<T>(plugin: PluginObject<T> | PluginFunction<T>, options?: T): void;
   static mixin(mixin: typeof Vue | ComponentOptions): void;
-  static compile(template: string): { render: Function, staticRenderFns: Function };
+  static compile(template: string): {
+    render(createElement: typeof Vue.prototype.$createElement): VNode;
+    staticRenderFns: (() => VNode)[];
+  };
 }