Evan You 3 роки тому
батько
коміт
206f8a7f09

+ 2 - 1
src/types/component.ts

@@ -1,6 +1,7 @@
 import type VNode from 'core/vdom/vnode'
 import type Watcher from 'core/observer/watcher'
-import { ComponentOptions, SetupContext } from './options'
+import { ComponentOptions } from './options'
+import { SetupContext } from 'v3/apiSetup'
 import { ScopedSlotsData, VNodeChildren, VNodeData } from './vnode'
 import { GlobalAPI } from './global-api'
 import { EffectScope } from 'v3/reactivity/effectScope'

+ 2 - 10
src/types/options.ts

@@ -1,5 +1,6 @@
 import VNode from 'core/vdom/vnode'
-import { DebuggerEvent } from 'v3'
+import { DebuggerEvent } from 'v3/debug'
+import { SetupContext } from 'v3/apiSetup'
 import { Component } from './component'
 
 export type InternalComponentOptions = {
@@ -12,15 +13,6 @@ export type InternalComponentOptions = {
 
 type InjectKey = string | Symbol
 
-/**
- * @internal
- */
-export interface SetupContext {
-  attrs: Record<string, any>
-  slots: Record<string, () => VNode[]>
-  emit: (event: string, ...args: any[]) => any
-}
-
 /**
  * @internal
  */

+ 9 - 1
src/v3/apiSetup.ts

@@ -1,11 +1,19 @@
 import { Component } from 'types/component'
-import type { SetupContext } from 'types/options'
 import { def, invokeWithErrorHandling, isReserved, warn } from '../core/util'
 import VNode from '../core/vdom/vnode'
 import { bind, emptyObject, isFunction, isObject } from '../shared/util'
 import { currentInstance, setCurrentInstance } from './currentInstance'
 import { isRef } from './reactivity/ref'
 
+/**
+ * @internal
+ */
+export interface SetupContext {
+  attrs: Record<string, any>
+  slots: Record<string, () => VNode[]>
+  emit: (event: string, ...args: any[]) => any
+}
+
 export function initSetup(vm: Component) {
   const options = vm.$options
   const setup = options.setup

+ 7 - 0
src/v3/index.ts

@@ -74,4 +74,11 @@ export { useSlots, useAttrs } from './apiSetup'
 export { nextTick } from 'core/util/next-tick'
 export { set, del } from 'core/observer'
 
+/**
+ * @internal type is manually declared in <root>/types/v3-define-component.d.ts
+ */
+export function defineComponent(options: any) {
+  return options
+}
+
 export * from './apiLifecycle'

+ 15 - 0
types/common.d.ts

@@ -0,0 +1,15 @@
+export type Data = { [key: string]: unknown }
+
+export type UnionToIntersection<U> = (
+  U extends any ? (k: U) => void : never
+) extends (k: infer I) => void
+  ? I
+  : never
+
+// Conditional returns can enforce identical types.
+// See here: https://github.com/Microsoft/TypeScript/issues/27024#issuecomment-421529650
+// prettier-ignore
+type Equal<Left, Right> =
+  (<U>() => U extends Left ? 1 : 0) extends (<U>() => U extends Right ? 1 : 0) ? true : false;
+
+export type HasDefined<T> = Equal<T, unknown> extends true ? false : true

+ 34 - 3
types/index.d.ts

@@ -11,8 +11,8 @@ export {
   ComponentOptions,
   FunctionalComponentOptions,
   RenderContext,
-  PropType,
-  PropOptions,
+  // PropType,
+  // PropOptions,
   ComputedOptions,
   WatchHandler,
   WatchOptions,
@@ -32,5 +32,36 @@ export {
   VNodeDirective
 } from './vnode'
 
-export * from './v3'
+export * from './v3-manual-apis'
 export * from './v3-generated'
+
+export { Data } from './common'
+export { SetupContext } from './v3-setup-context'
+export { defineComponent } from './v3-define-component'
+// export { defineAsyncComponent } from './defineAsyncComponent'
+export {
+  SetupFunction,
+  // v2 already has option with same name and it's for a single computed
+  ComputedOptions as ComponentComputedOptions,
+  MethodOptions as ComponentMethodOptions,
+  ComponentPropsOptions
+} from './v3-component-options'
+export {
+  ComponentInstance,
+  ComponentPublicInstance,
+  ComponentRenderProxy
+} from './v3-component-proxy'
+export {
+  PropType,
+  PropOptions,
+  ExtractPropTypes,
+  ExtractDefaultPropTypes
+} from './v3-component-props'
+export {
+  DirectiveModifiers,
+  DirectiveBinding,
+  DirectiveHook,
+  ObjectDirective,
+  FunctionDirective,
+  Directive
+} from './v3-directive'

+ 3 - 35
types/options.d.ts

@@ -1,6 +1,7 @@
 import { Vue, CreateElement, CombinedVueInstance } from './vue'
 import { VNode, VNodeData, VNodeDirective, NormalizedScopedSlot } from './vnode'
-import { SetupContext } from './v3'
+import { SetupContext } from './v3-setup-context'
+import { DebuggerEvent } from './v3-generated'
 
 type Constructor = {
   new (...args: any[]): any
@@ -249,22 +250,10 @@ export interface RenderContext<Props = DefaultProps> {
   injections: any
 }
 
-export type Prop<T> =
-  | { (): T }
-  | { new (...args: never[]): T & object }
-  | { new (...args: string[]): Function }
-
-export type PropType<T> = Prop<T> | Prop<T>[]
+import { PropOptions, PropType } from './v3-component-props'
 
 export type PropValidator<T> = PropOptions<T> | PropType<T>
 
-export interface PropOptions<T = any> {
-  type?: PropType<T>
-  required?: boolean
-  default?: T | null | undefined | (() => T | null | undefined)
-  validator?(value: T): boolean
-}
-
 export type RecordPropsDefinition<T> = {
   [K in keyof T]: PropValidator<T[K]>
 }
@@ -316,24 +305,3 @@ export type InjectOptions =
       [key: string]: InjectKey | { from?: InjectKey; default?: any }
     }
   | string[]
-
-export type DebuggerEvent = {
-  target: object
-  type: TrackOpTypes | TriggerOpTypes
-  key?: any
-  newValue?: any
-  oldValue?: any
-  oldTarget?: Map<any, any> | Set<any>
-}
-
-export const enum TrackOpTypes {
-  GET = 'get',
-  TOUCH = 'touch'
-}
-
-export const enum TriggerOpTypes {
-  SET = 'set',
-  ADD = 'add',
-  DELETE = 'delete',
-  ARRAY_MUTATION = 'array mutation'
-}

+ 49 - 1
types/test/v3/setup-test.ts

@@ -1,4 +1,4 @@
-import Vue from '../../index'
+import Vue, { defineComponent } from '../../index'
 
 // object props
 Vue.extend({
@@ -30,3 +30,51 @@ Vue.extend({
     ctx.slots.default && ctx.slots.default()
   }
 })
+
+// object props
+defineComponent({
+  props: {
+    foo: String,
+    bar: Number
+  },
+  setup(props) {
+    // @ts-expect-error
+    props.foo.slice(1, 2)
+
+    props.foo?.slice(1, 2)
+
+    // @ts-expect-error
+    props.bar + 123
+
+    props.bar?.toFixed(2)
+  }
+})
+
+// array props
+defineComponent({
+  props: ['foo', 'bar'],
+  setup(props) {
+    props.foo
+    props.bar
+  }
+})
+
+// context
+defineComponent({
+  emits: ['foo'],
+  setup(_props, ctx) {
+    if (ctx.attrs.id) {
+    }
+    ctx.emit('foo')
+    // @ts-expect-error
+    ctx.emit('ok')
+    ctx.slots.default && ctx.slots.default()
+  },
+  methods: {
+    foo() {
+      this.$emit('foo')
+      // @ts-expect-error
+      this.$emit('bar')
+    }
+  }
+})

+ 1 - 1
types/tsconfig.json

@@ -12,6 +12,6 @@
       "vue": ["../index.d.ts"]
     }
   },
-  "include": ["./*.d.ts", "*.ts"],
+  "include": ["."],
   "compileOnSave": false
 }

+ 120 - 0
types/v3-component-options.d.ts

@@ -0,0 +1,120 @@
+import { Vue } from './vue'
+import { VNode } from './vnode'
+import { ComponentOptions as Vue2ComponentOptions } from './options'
+import { EmitsOptions, SetupContext } from './v3-setup-context'
+import { Data } from './common'
+import { ComponentPropsOptions, ExtractPropTypes } from './v3-component-props'
+import { ComponentRenderProxy } from './v3-component-proxy'
+export { ComponentPropsOptions } from './v3-component-props'
+
+export type ComputedGetter<T> = (ctx?: any) => T
+export type ComputedSetter<T> = (v: T) => void
+
+export interface WritableComputedOptions<T> {
+  get: ComputedGetter<T>
+  set: ComputedSetter<T>
+}
+
+export type ComputedOptions = Record<
+  string,
+  ComputedGetter<any> | WritableComputedOptions<any>
+>
+
+export interface MethodOptions {
+  [key: string]: Function
+}
+
+export type SetupFunction<
+  Props,
+  RawBindings = {},
+  Emits extends EmitsOptions = {}
+> = (
+  this: void,
+  props: Readonly<Props>,
+  ctx: SetupContext<Emits>
+) => RawBindings | (() => VNode | null) | void
+
+interface ComponentOptionsBase<
+  Props,
+  D = Data,
+  C extends ComputedOptions = {},
+  M extends MethodOptions = {}
+> extends Omit<
+    Vue2ComponentOptions<Vue, D, M, C, Props>,
+    'data' | 'computed' | 'method' | 'setup' | 'props'
+  > {
+  // allow any custom options
+  [key: string]: any
+
+  // rewrite options api types
+  data?: (this: Props & Vue, vm: Props) => D
+  computed?: C
+  methods?: M
+}
+
+export type ExtractComputedReturns<T extends any> = {
+  [key in keyof T]: T[key] extends { get: (...args: any[]) => infer TReturn }
+    ? TReturn
+    : T[key] extends (...args: any[]) => infer TReturn
+    ? TReturn
+    : never
+}
+
+export type ComponentOptionsWithProps<
+  PropsOptions = ComponentPropsOptions,
+  RawBindings = Data,
+  D = Data,
+  C extends ComputedOptions = {},
+  M extends MethodOptions = {},
+  Mixin = {},
+  Extends = {},
+  Emits extends EmitsOptions = {},
+  EmitsNames extends string = string,
+  Props = ExtractPropTypes<PropsOptions>
+> = ComponentOptionsBase<Props, D, C, M> & {
+  props?: PropsOptions
+  emits?: (Emits | EmitsNames[]) & ThisType<void>
+  setup?: SetupFunction<Props, RawBindings, Emits>
+} & ThisType<
+    ComponentRenderProxy<Props, RawBindings, D, C, M, Mixin, Extends, Emits>
+  >
+
+export type ComponentOptionsWithArrayProps<
+  PropNames extends string = string,
+  RawBindings = Data,
+  D = Data,
+  C extends ComputedOptions = {},
+  M extends MethodOptions = {},
+  Mixin = {},
+  Extends = {},
+  Emits extends EmitsOptions = {},
+  EmitsNames extends string = string,
+  Props = Readonly<{ [key in PropNames]?: any }>
+> = ComponentOptionsBase<Props, D, C, M> & {
+  props?: PropNames[]
+  emits?: (Emits | EmitsNames[]) & ThisType<void>
+  setup?: SetupFunction<Props, RawBindings, Emits>
+} & ThisType<
+    ComponentRenderProxy<Props, RawBindings, D, C, M, Mixin, Extends, Emits>
+  >
+
+export type ComponentOptionsWithoutProps<
+  Props = {},
+  RawBindings = Data,
+  D = Data,
+  C extends ComputedOptions = {},
+  M extends MethodOptions = {},
+  Mixin = {},
+  Extends = {},
+  Emits extends EmitsOptions = {},
+  EmitsNames extends string = string
+> = ComponentOptionsBase<Props, D, C, M> & {
+  props?: undefined
+  emits?: (Emits | EmitsNames[]) & ThisType<void>
+  setup?: SetupFunction<Props, RawBindings, Emits>
+} & ThisType<
+    ComponentRenderProxy<Props, RawBindings, D, C, M, Mixin, Extends, Emits>
+  >
+
+export type WithLegacyAPI<T, D, C, M, Props> = T &
+  Omit<Vue2ComponentOptions<Vue, D, M, C, Props>, keyof T>

+ 100 - 0
types/v3-component-props.d.ts

@@ -0,0 +1,100 @@
+import { Data } from './common'
+
+export type ComponentPropsOptions<P = Data> =
+  | ComponentObjectPropsOptions<P>
+  | string[]
+
+export type ComponentObjectPropsOptions<P = Data> = {
+  [K in keyof P]: Prop<P[K]> | null
+}
+
+export type Prop<T, D = T> = PropOptions<T, D> | PropType<T>
+
+type DefaultFactory<T> = () => T | null | undefined
+
+export interface PropOptions<T = any, D = T> {
+  type?: PropType<T> | true | null
+  required?: boolean
+  default?: D | DefaultFactory<D> | null | undefined | object
+  validator?(value: unknown): boolean
+}
+
+export type PropType<T> = PropConstructor<T> | PropConstructor<T>[]
+
+type PropConstructor<T> =
+  | { new (...args: any[]): T & object }
+  | { (): T }
+  | { new (...args: string[]): Function }
+
+type RequiredKeys<T> = {
+  [K in keyof T]: T[K] extends
+    | { required: true }
+    | { default: any }
+    | BooleanConstructor
+    | { type: BooleanConstructor }
+    ? K
+    : never
+}[keyof T]
+
+type OptionalKeys<T> = Exclude<keyof T, RequiredKeys<T>>
+
+type ExtractFunctionPropType<
+  T extends Function,
+  TArgs extends Array<any> = any[],
+  TResult = any
+> = T extends (...args: TArgs) => TResult ? T : never
+
+type ExtractCorrectPropType<T> = T extends Function
+  ? ExtractFunctionPropType<T>
+  : Exclude<T, Function>
+
+// prettier-ignore
+type InferPropType<T> = T extends null
+  ? any // null & true would fail to infer
+  : T extends { type: null | true }
+    ? any // As TS issue https://github.com/Microsoft/TypeScript/issues/14829 // somehow `ObjectConstructor` when inferred from { (): T } becomes `any` // `BooleanConstructor` when inferred from PropConstructor(with PropMethod) becomes `Boolean`
+    : T extends ObjectConstructor | { type: ObjectConstructor }
+      ? Record<string, any>
+      : T extends BooleanConstructor | { type: BooleanConstructor }
+        ? boolean
+          : T extends DateConstructor | { type: DateConstructor}
+            ? Date
+              : T extends FunctionConstructor
+                ? Function
+                : T extends Prop<infer V, infer D>
+                  ? unknown extends V
+                    ? D extends null | undefined
+                      ? V
+                      : D
+                    : ExtractCorrectPropType<V>
+                  : T
+
+export type ExtractPropTypes<O> = {
+  // use `keyof Pick<O, RequiredKeys<O>>` instead of `RequiredKeys<O>` to support IDE features
+  [K in keyof Pick<O, RequiredKeys<O>>]: InferPropType<O[K]>
+} & {
+  // use `keyof Pick<O, OptionalKeys<O>>` instead of `OptionalKeys<O>` to support IDE features
+  [K in keyof Pick<O, OptionalKeys<O>>]?: InferPropType<O[K]>
+}
+
+type DefaultKeys<T> = {
+  [K in keyof T]: T[K] extends
+    | {
+        default: any
+      }
+    | BooleanConstructor
+    | { type: BooleanConstructor }
+    ? T[K] extends {
+        type: BooleanConstructor
+        required: true
+      }
+      ? never
+      : K
+    : never
+}[keyof T]
+
+// extract props which defined with default from prop options
+export type ExtractDefaultPropTypes<O> = O extends object
+  ? // use `keyof Pick<O, DefaultKeys<O>>` instead of `DefaultKeys<O>` to support IDE features
+    { [K in keyof Pick<O, DefaultKeys<O>>]: InferPropType<O[K]> }
+  : {}

+ 189 - 0
types/v3-component-proxy.d.ts

@@ -0,0 +1,189 @@
+import { ExtractDefaultPropTypes, ExtractPropTypes } from './v3-component-props'
+import {
+  nextTick,
+  ShallowUnwrapRef,
+  UnwrapNestedRefs,
+  WatchOptions,
+  WatchStopHandle
+} from './v3-generated'
+import { Data } from './common'
+
+import { Vue, VueConstructor } from './vue'
+import { ComponentOptions as Vue2ComponentOptions } from './options'
+import {
+  ComputedOptions,
+  MethodOptions,
+  ExtractComputedReturns
+} from './v3-component-options'
+import {
+  ComponentRenderEmitFn,
+  EmitFn,
+  EmitsOptions,
+  ObjectEmitsOptions,
+  Slots
+} from './v3-setup-context'
+
+type EmitsToProps<T extends EmitsOptions> = T extends string[]
+  ? {
+      [K in string & `on${Capitalize<T[number]>}`]?: (...args: any[]) => any
+    }
+  : T extends ObjectEmitsOptions
+  ? {
+      [K in string &
+        `on${Capitalize<string & keyof T>}`]?: K extends `on${infer C}`
+        ? T[Uncapitalize<C>] extends null
+          ? (...args: any[]) => any
+          : (
+              ...args: T[Uncapitalize<C>] extends (...args: infer P) => any
+                ? P
+                : never
+            ) => any
+        : never
+    }
+  : {}
+
+export type ComponentInstance = InstanceType<VueConstructor>
+
+// public properties exposed on the proxy, which is used as the render context
+// in templates (as `this` in the render option)
+export type ComponentRenderProxy<
+  P = {}, // props type extracted from props option
+  B = {}, // raw bindings returned from setup()
+  D = {}, // return from data()
+  C extends ComputedOptions = {},
+  M extends MethodOptions = {},
+  Mixin = {},
+  Extends = {},
+  Emits extends EmitsOptions = {},
+  PublicProps = P,
+  Defaults = {},
+  MakeDefaultsOptional extends boolean = false
+> = {
+  $data: D
+  $props: Readonly<
+    MakeDefaultsOptional extends true
+      ? Partial<Defaults> & Omit<P & PublicProps, keyof Defaults>
+      : P & PublicProps
+  >
+  $attrs: Record<string, string>
+  $emit: ComponentRenderEmitFn<
+    Emits,
+    keyof Emits,
+    ComponentRenderProxy<
+      P,
+      B,
+      D,
+      C,
+      M,
+      Mixin,
+      Extends,
+      Emits,
+      PublicProps,
+      Defaults,
+      MakeDefaultsOptional
+    >
+  >
+} & Readonly<P> &
+  ShallowUnwrapRef<B> &
+  D &
+  M &
+  ExtractComputedReturns<C> &
+  Omit<Vue, '$data' | '$props' | '$attrs' | '$emit'>
+
+// for Vetur and TSX support
+type VueConstructorProxy<
+  PropsOptions,
+  RawBindings,
+  Data,
+  Computed extends ComputedOptions,
+  Methods extends MethodOptions,
+  Mixin = {},
+  Extends = {},
+  Emits extends EmitsOptions = {},
+  Props = ExtractPropTypes<PropsOptions> &
+    ({} extends Emits ? {} : EmitsToProps<Emits>)
+> = Omit<VueConstructor, never> & {
+  new (...args: any[]): ComponentRenderProxy<
+    Props,
+    ShallowUnwrapRef<RawBindings>,
+    Data,
+    Computed,
+    Methods,
+    Mixin,
+    Extends,
+    Emits,
+    Props,
+    ExtractDefaultPropTypes<PropsOptions>,
+    true
+  >
+}
+
+type DefaultData<V> = object | ((this: V) => object)
+type DefaultMethods<V> = { [key: string]: (this: V, ...args: any[]) => any }
+type DefaultComputed = { [key: string]: any }
+
+export type VueProxy<
+  PropsOptions,
+  RawBindings,
+  Data = DefaultData<Vue>,
+  Computed extends ComputedOptions = DefaultComputed,
+  Methods extends MethodOptions = DefaultMethods<Vue>,
+  Mixin = {},
+  Extends = {},
+  Emits extends EmitsOptions = {}
+> = Vue2ComponentOptions<
+  Vue,
+  ShallowUnwrapRef<RawBindings> & Data,
+  Methods,
+  Computed,
+  PropsOptions,
+  ExtractPropTypes<PropsOptions>
+> &
+  VueConstructorProxy<
+    PropsOptions,
+    RawBindings,
+    Data,
+    Computed,
+    Methods,
+    Mixin,
+    Extends,
+    Emits
+  >
+
+// public properties exposed on the proxy, which is used as the render context
+// in templates (as `this` in the render option)
+export type ComponentPublicInstance<
+  P = {}, // props type extracted from props option
+  B = {}, // raw bindings returned from setup()
+  D = {}, // return from data()
+  C extends ComputedOptions = {},
+  M extends MethodOptions = {},
+  E extends EmitsOptions = {},
+  PublicProps = P,
+  Defaults = {},
+  MakeDefaultsOptional extends boolean = false
+> = {
+  $data: D
+  $props: MakeDefaultsOptional extends true
+    ? Partial<Defaults> & Omit<P & PublicProps, keyof Defaults>
+    : P & PublicProps
+  $attrs: Data
+  $refs: Data
+  $slots: Slots
+  $root: ComponentPublicInstance | null
+  $parent: ComponentPublicInstance | null
+  $emit: EmitFn<E>
+  $el: any
+  // $options: Options & MergedComponentOptionsOverride
+  $forceUpdate: () => void
+  $nextTick: typeof nextTick
+  $watch(
+    source: string | Function,
+    cb: Function,
+    options?: WatchOptions
+  ): WatchStopHandle
+} & P &
+  ShallowUnwrapRef<B> &
+  UnwrapNestedRefs<D> &
+  ExtractComputedReturns<C> &
+  M

+ 119 - 0
types/v3-define-component.d.ts

@@ -0,0 +1,119 @@
+import { ComponentPropsOptions } from './v3-component-props'
+import {
+  MethodOptions,
+  ComputedOptions,
+  ComponentOptionsWithoutProps,
+  ComponentOptionsWithArrayProps,
+  ComponentOptionsWithProps
+} from './v3-component-options'
+import { VueProxy } from './v3-component-proxy'
+import { Data, HasDefined } from './common'
+import { EmitsOptions } from './v3-setup-context'
+
+/**
+ * overload 1: object format with no props
+ */
+export function defineComponent<
+  RawBindings,
+  D = Data,
+  C extends ComputedOptions = {},
+  M extends MethodOptions = {},
+  Mixin = {},
+  Extends = {},
+  Emits extends EmitsOptions = {},
+  EmitsNames extends string = string
+>(
+  options: ComponentOptionsWithoutProps<
+    {},
+    RawBindings,
+    D,
+    C,
+    M,
+    Mixin,
+    Extends,
+    Emits,
+    EmitsNames
+  >
+): VueProxy<{}, RawBindings, D, C, M, Mixin, Extends, Emits>
+/**
+ * overload 2: object format with array props declaration
+ * props inferred as `{ [key in PropNames]?: any }`
+ *
+ * return type is for Vetur and TSX support
+ */
+export function defineComponent<
+  PropNames extends string,
+  RawBindings = Data,
+  D = Data,
+  C extends ComputedOptions = {},
+  M extends MethodOptions = {},
+  Mixin = {},
+  Extends = {},
+  Emits extends EmitsOptions = {},
+  EmitsNames extends string = string,
+  PropsOptions extends ComponentPropsOptions = ComponentPropsOptions
+>(
+  options: ComponentOptionsWithArrayProps<
+    PropNames,
+    RawBindings,
+    D,
+    C,
+    M,
+    Mixin,
+    Extends,
+    Emits,
+    EmitsNames
+  >
+): VueProxy<
+  Readonly<{ [key in PropNames]?: any }>,
+  RawBindings,
+  D,
+  C,
+  M,
+  Mixin,
+  Extends,
+  Emits
+>
+
+/**
+ * overload 3: object format with object props declaration
+ *
+ * see `ExtractPropTypes` in './componentProps.ts'
+ */
+export function defineComponent<
+  Props,
+  RawBindings = Data,
+  D = Data,
+  C extends ComputedOptions = {},
+  M extends MethodOptions = {},
+  Mixin = {},
+  Extends = {},
+  Emits extends EmitsOptions = {},
+  EmitsNames extends string = string,
+  PropsOptions extends ComponentPropsOptions = ComponentPropsOptions
+>(
+  options: HasDefined<Props> extends true
+    ? ComponentOptionsWithProps<
+        PropsOptions,
+        RawBindings,
+        D,
+        C,
+        M,
+        Mixin,
+        Extends,
+        Emits,
+        EmitsNames,
+        Props
+      >
+    : ComponentOptionsWithProps<
+        PropsOptions,
+        RawBindings,
+        D,
+        C,
+        M,
+        Mixin,
+        Extends,
+        Emits,
+        EmitsNames
+      >
+): VueProxy<PropsOptions, RawBindings, D, C, M, Mixin, Extends, Emits>

+ 29 - 0
types/v3-directive.ts

@@ -0,0 +1,29 @@
+import type { VNodeDirective, VNode } from './vnode'
+
+export type DirectiveModifiers = Record<string, boolean>
+
+export interface DirectiveBinding<V> extends Readonly<VNodeDirective> {
+  readonly modifiers: DirectiveModifiers
+  readonly value: V
+  readonly oldValue: V | null
+}
+
+export type DirectiveHook<T = any, Prev = VNode | null, V = any> = (
+  el: T,
+  binding: DirectiveBinding<V>,
+  vnode: VNode,
+  prevVNode: Prev
+) => void
+
+export interface ObjectDirective<T = any, V = any> {
+  bind?: DirectiveHook<T, any, V>
+  inserted?: DirectiveHook<T, any, V>
+  update?: DirectiveHook<T, any, V>
+  componentUpdated?: DirectiveHook<T, any, V>
+  unbind?: DirectiveHook<T, any, V>
+}
+export type FunctionDirective<T = any, V = any> = DirectiveHook<T, any, V>
+
+export type Directive<T = any, V = any> =
+  | ObjectDirective<T, V>
+  | FunctionDirective<T, V>

+ 1 - 7
types/v3.d.ts → types/v3-manual-apis.d.ts

@@ -1,12 +1,6 @@
-import { VNode } from './vnode'
+import { SetupContext } from './v3-setup-context'
 import { CreateElement, Vue } from './vue'
 
-export interface SetupContext {
-  attrs: Record<string, any>
-  slots: Record<string, (() => VNode[]) | undefined>
-  emit: (event: string, ...args: any[]) => any
-}
-
 export function getCurrentInstance(): { proxy: Vue } | null
 
 export const h: CreateElement

+ 42 - 0
types/v3-setup-context.d.ts

@@ -0,0 +1,42 @@
+import { VNode } from './vnode'
+import { Data, UnionToIntersection } from './common'
+import { Vue } from './vue'
+
+export type Slot = (...args: any[]) => VNode[]
+
+export type Slots = Record<string, Slot | undefined>
+
+export type ObjectEmitsOptions = Record<
+  string,
+  ((...args: any[]) => any) | null
+>
+
+export type EmitsOptions = ObjectEmitsOptions | string[]
+
+export type EmitFn<
+  Options = ObjectEmitsOptions,
+  Event extends keyof Options = keyof Options,
+  ReturnType extends void | Vue = void
+> = Options extends Array<infer V>
+  ? (event: V, ...args: any[]) => ReturnType
+  : {} extends Options // if the emit is empty object (usually the default value for emit) should be converted to function
+  ? (event: string, ...args: any[]) => ReturnType
+  : UnionToIntersection<
+      {
+        [key in Event]: Options[key] extends (...args: infer Args) => any
+          ? (event: key, ...args: Args) => ReturnType
+          : (event: key, ...args: any[]) => ReturnType
+      }[Event]
+    >
+
+export type ComponentRenderEmitFn<
+  Options = ObjectEmitsOptions,
+  Event extends keyof Options = keyof Options,
+  T extends Vue | void = void
+> = EmitFn<Options, Event, T>
+
+export interface SetupContext<E extends EmitsOptions = {}> {
+  attrs: Data
+  slots: Slots
+  emit: EmitFn<E>
+}