From 19d37b70fa0e80b8d15dc573e7e95acb854d0016 Mon Sep 17 00:00:00 2001 From: pikax Date: Tue, 18 Aug 2020 08:25:51 +0100 Subject: [PATCH 01/24] types(runtime-core): move jsx defineComponent to jsx.d.ts --- .../runtime-core/src/apiNewDefineComponent.ts | 222 ++++++++++++++++++ packages/runtime-core/src/index.ts | 4 +- packages/runtime-dom/types/jsx.d.ts | 26 ++ test-dts/componentTypeExtensions.test-d.tsx | 49 +++- test-dts/defineComponent.test-d.tsx | 38 ++- 5 files changed, 336 insertions(+), 3 deletions(-) create mode 100644 packages/runtime-core/src/apiNewDefineComponent.ts diff --git a/packages/runtime-core/src/apiNewDefineComponent.ts b/packages/runtime-core/src/apiNewDefineComponent.ts new file mode 100644 index 00000000000..5cc7af178be --- /dev/null +++ b/packages/runtime-core/src/apiNewDefineComponent.ts @@ -0,0 +1,222 @@ +import { + ComputedOptions, + MethodOptions, + ComponentOptionsWithoutProps, + ComponentOptionsWithArrayProps, + ComponentOptionsWithObjectProps, + ComponentOptionsMixin, + RenderFunction +} from './componentOptions' +import { + SetupContext, + FunctionalComponent, + AllowedComponentProps, + ComponentCustomProps +} from './component' +import { + CreateComponentPublicInstance, + ComponentPublicInstanceConstructor +} from './componentProxy' +import { ExtractPropTypes, ComponentPropsOptions } from './componentProps' +import { EmitsOptions } from './componentEmits' +import { isFunction } from '@vue/shared' +import { VNodeProps } from './vnode' + +export interface DefineJSX< + Props, + RawBindings, + D, + C extends ComputedOptions = {}, + M extends MethodOptions = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + E extends EmitsOptions = Record, + PublicProps = {} +> {} + +// newDefineComponent is a utility that is primarily used for type inference +// when declaring components. Type inference is provided in the component +// options (provided as the argument). The returned value has artificial types +// for TSX / manual render function / IDE support. + +// overload 1: direct setup function +// (uses user defined props interface) +export function newDefineComponent( + setup: ( + props: Readonly, + ctx: SetupContext + ) => RawBindings | RenderFunction +): DefineJSX< + Props, + RawBindings, + {}, + {}, + {}, + {}, + {}, + {}, + // public props + VNodeProps & Props & AllowedComponentProps & ComponentCustomProps +> & + FunctionalComponent + +// overload 2: object format with no props +// (uses user defined props interface) +// return type is for Vetur and TSX support +export function newDefineComponent< + Props = {}, + RawBindings = {}, + D = {}, + C extends ComputedOptions = {}, + M extends MethodOptions = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + E extends EmitsOptions = Record, + EE extends string = string +>( + options: ComponentOptionsWithoutProps< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE + > + /** + * Props, + RawBindings, + D, + C extends ComputedOptions = {}, + M extends MethodOptions = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + E extends EmitsOptions = Record, + PublicProps = {} + */ +): DefineJSX< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + VNodeProps & Props & AllowedComponentProps & ComponentCustomProps +> & + ComponentOptionsWithoutProps< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE + > + +// overload 3: object format with array props declaration +// props inferred as { [key in PropNames]?: any } +// return type is for Vetur and TSX support +export function newDefineComponent< + PropNames extends string, + RawBindings, + D, + C extends ComputedOptions = {}, + M extends MethodOptions = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + E extends EmitsOptions = Record, + EE extends string = string +>( + options: ComponentOptionsWithArrayProps< + PropNames, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE + > +): DefineJSX< + Readonly<{ [key in PropNames]?: any }>, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + AllowedComponentProps & ComponentCustomProps +> & + ComponentOptionsWithArrayProps< + PropNames, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE + > + +// overload 4: object format with object props declaration +// see `ExtractPropTypes` in ./componentProps.ts +export function newDefineComponent< + // the Readonly constraint allows TS to treat the type of { required: true } + // as constant instead of boolean. + PropsOptions extends Readonly, + RawBindings, + D, + C extends ComputedOptions = {}, + M extends MethodOptions = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + E extends EmitsOptions = Record, + EE extends string = string +>( + options: ComponentOptionsWithObjectProps< + PropsOptions, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE + > +): DefineJSX< + ExtractPropTypes, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + VNodeProps & AllowedComponentProps & ComponentCustomProps +> & + ComponentOptionsWithObjectProps< + PropsOptions, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE + > + +// implementation, close to no-op +export function newDefineComponent(options: unknown) { + return isFunction(options) ? { setup: options, name: options.name } : options +} diff --git a/packages/runtime-core/src/index.ts b/packages/runtime-core/src/index.ts index 14283b5d46b..09e2d08562b 100644 --- a/packages/runtime-core/src/index.ts +++ b/packages/runtime-core/src/index.ts @@ -42,6 +42,7 @@ export { export { provide, inject } from './apiInject' export { nextTick } from './scheduler' export { defineComponent } from './apiDefineComponent' +export { newDefineComponent, DefineJSX } from './apiNewDefineComponent' export { defineAsyncComponent } from './apiAsyncComponent' // Advanced API ---------------------------------------------------------------- @@ -177,7 +178,8 @@ export { } from './componentOptions' export { ComponentPublicInstance, - ComponentCustomProperties + ComponentCustomProperties, + CreateComponentPublicInstance } from './componentProxy' export { Renderer, diff --git a/packages/runtime-dom/types/jsx.d.ts b/packages/runtime-dom/types/jsx.d.ts index 82a3ab851df..44f4d0387b5 100644 --- a/packages/runtime-dom/types/jsx.d.ts +++ b/packages/runtime-dom/types/jsx.d.ts @@ -1352,3 +1352,29 @@ declare global { // suppress ts:2669 export {} + +declare module '@vue/runtime-core' { + interface DefineJSX< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + PublicProps + > { + new (): RuntimeCore.CreateComponentPublicInstance< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + PublicProps + > + } +} diff --git a/test-dts/componentTypeExtensions.test-d.tsx b/test-dts/componentTypeExtensions.test-d.tsx index 32a72f844e6..5e52310a344 100644 --- a/test-dts/componentTypeExtensions.test-d.tsx +++ b/test-dts/componentTypeExtensions.test-d.tsx @@ -1,4 +1,9 @@ -import { defineComponent, expectError, expectType } from './index' +import { + defineComponent, + expectError, + expectType, + newDefineComponent +} from './index' declare module '@vue/runtime-core' { interface ComponentCustomOptions { @@ -55,3 +60,45 @@ expectError() expectError() // @ts-expect-error expectError() + +const Custom2 = newDefineComponent({ + props: { + bar: String, + baz: { + type: Number, + required: true + } + }, + + data: () => ({ counter: 0 }), + + test(n) { + expectType(n) + }, + + methods: { + aMethod() { + // @ts-expect-error + expectError(this.notExisting) + this.counter++ + this.state = 'running' + // @ts-expect-error + expectError((this.state = 'not valid')) + } + } +}) + +expectType() +expectType() +expectType() + +// @ts-expect-error +expectType() +// @ts-expect-error +expectError() +// @ts-expect-error +expectError() +// @ts-expect-error +expectError() +// @ts-expect-error +expectError() diff --git a/test-dts/defineComponent.test-d.tsx b/test-dts/defineComponent.test-d.tsx index b65ca88ae89..f00d54bc317 100644 --- a/test-dts/defineComponent.test-d.tsx +++ b/test-dts/defineComponent.test-d.tsx @@ -9,7 +9,15 @@ import { expectType, ComponentPublicInstance, ComponentOptions, - SetupContext + SetupContext, + FunctionalComponent, + h, + Component, + ComponentOptionsWithoutProps, + ComponentOptionsWithArrayProps, + ComponentOptionsWithObjectProps, + ComponentPropsOptions, + newDefineComponent } from './index' describe('with object props', () => { @@ -735,3 +743,31 @@ describe('componentOptions setup should be `SetupContext`', () => { ctx: SetupContext ) => any) }) + +const Wprops = defineComponent({ + props: { + x1: { + type: String, + required: true + }, + x2: Number + } +}) + +const Xprops = newDefineComponent({ + props: { + x1: { + type: String, + required: true + }, + x2: Number + } +}) + +// @ts-expect-error +expectType() + +// @ts-expect-error +expectError() +// @ts-expect-error +expectError() From a70b614684c1b44bcd135477cec916d64a9adbff Mon Sep 17 00:00:00 2001 From: pikax Date: Tue, 18 Aug 2020 08:39:45 +0100 Subject: [PATCH 02/24] chore: improve return type for defineComponent --- .../runtime-core/src/apiNewDefineComponent.ts | 103 ++++++++---------- packages/runtime-core/src/index.ts | 6 +- packages/runtime-dom/types/jsx.d.ts | 24 +--- 3 files changed, 50 insertions(+), 83 deletions(-) diff --git a/packages/runtime-core/src/apiNewDefineComponent.ts b/packages/runtime-core/src/apiNewDefineComponent.ts index 5cc7af178be..ae0c4865edc 100644 --- a/packages/runtime-core/src/apiNewDefineComponent.ts +++ b/packages/runtime-core/src/apiNewDefineComponent.ts @@ -9,20 +9,26 @@ import { } from './componentOptions' import { SetupContext, - FunctionalComponent, AllowedComponentProps, ComponentCustomProps } from './component' -import { - CreateComponentPublicInstance, - ComponentPublicInstanceConstructor -} from './componentProxy' import { ExtractPropTypes, ComponentPropsOptions } from './componentProps' import { EmitsOptions } from './componentEmits' import { isFunction } from '@vue/shared' import { VNodeProps } from './vnode' +import { + CreateComponentPublicInstance, + ComponentPublicInstance +} from './componentProxy' + +declare const DefineComponent: unique symbol +declare const JSX: unique symbol -export interface DefineJSX< +export interface DefineComponentJSX { + [JSX]: true +} + +export type DefineComponent< Props, RawBindings, D, @@ -32,7 +38,29 @@ export interface DefineJSX< Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = Record, PublicProps = {} -> {} +> = CreateComponentPublicInstance< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + PublicProps +> & { [DefineComponent]: true } & DefineComponentJSX< + CreateComponentPublicInstance< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + PublicProps + > + > // newDefineComponent is a utility that is primarily used for type inference // when declaring components. Type inference is provided in the component @@ -46,7 +74,7 @@ export function newDefineComponent( props: Readonly, ctx: SetupContext ) => RawBindings | RenderFunction -): DefineJSX< +): DefineComponent< Props, RawBindings, {}, @@ -57,8 +85,7 @@ export function newDefineComponent( {}, // public props VNodeProps & Props & AllowedComponentProps & ComponentCustomProps -> & - FunctionalComponent +> // overload 2: object format with no props // (uses user defined props interface) @@ -85,18 +112,7 @@ export function newDefineComponent< E, EE > - /** - * Props, - RawBindings, - D, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, - Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, - Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = Record, - PublicProps = {} - */ -): DefineJSX< +): DefineComponent< Props, RawBindings, D, @@ -106,18 +122,7 @@ export function newDefineComponent< Extends, E, VNodeProps & Props & AllowedComponentProps & ComponentCustomProps -> & - ComponentOptionsWithoutProps< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE - > +> // overload 3: object format with array props declaration // props inferred as { [key in PropNames]?: any } @@ -144,7 +149,7 @@ export function newDefineComponent< E, EE > -): DefineJSX< +): DefineComponent< Readonly<{ [key in PropNames]?: any }>, RawBindings, D, @@ -154,18 +159,7 @@ export function newDefineComponent< Extends, E, AllowedComponentProps & ComponentCustomProps -> & - ComponentOptionsWithArrayProps< - PropNames, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE - > +> // overload 4: object format with object props declaration // see `ExtractPropTypes` in ./componentProps.ts @@ -193,7 +187,7 @@ export function newDefineComponent< E, EE > -): DefineJSX< +): DefineComponent< ExtractPropTypes, RawBindings, D, @@ -203,18 +197,7 @@ export function newDefineComponent< Extends, E, VNodeProps & AllowedComponentProps & ComponentCustomProps -> & - ComponentOptionsWithObjectProps< - PropsOptions, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE - > +> // implementation, close to no-op export function newDefineComponent(options: unknown) { diff --git a/packages/runtime-core/src/index.ts b/packages/runtime-core/src/index.ts index 09e2d08562b..e22af985c61 100644 --- a/packages/runtime-core/src/index.ts +++ b/packages/runtime-core/src/index.ts @@ -42,7 +42,11 @@ export { export { provide, inject } from './apiInject' export { nextTick } from './scheduler' export { defineComponent } from './apiDefineComponent' -export { newDefineComponent, DefineJSX } from './apiNewDefineComponent' +export { + newDefineComponent, + DefineComponentJSX, + DefineComponent +} from './apiNewDefineComponent' export { defineAsyncComponent } from './apiAsyncComponent' // Advanced API ---------------------------------------------------------------- diff --git a/packages/runtime-dom/types/jsx.d.ts b/packages/runtime-dom/types/jsx.d.ts index 44f4d0387b5..1273d575409 100644 --- a/packages/runtime-dom/types/jsx.d.ts +++ b/packages/runtime-dom/types/jsx.d.ts @@ -1354,27 +1354,7 @@ declare global { export {} declare module '@vue/runtime-core' { - interface DefineJSX< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - PublicProps - > { - new (): RuntimeCore.CreateComponentPublicInstance< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - PublicProps - > + interface DefineComponentJSX { + new (): T } } From 084a090031d60f44ea20409b2b41f566d1b53e70 Mon Sep 17 00:00:00 2001 From: pikax Date: Tue, 18 Aug 2020 08:42:29 +0100 Subject: [PATCH 03/24] chore: replace apiDefineComponet --- .../runtime-core/src/apiDefineComponent.ts | 188 ++++++++-------- .../runtime-core/src/apiNewDefineComponent.ts | 205 ------------------ packages/runtime-core/src/index.ts | 9 +- test-dts/defineComponent.test-d.tsx | 28 --- 4 files changed, 95 insertions(+), 335 deletions(-) delete mode 100644 packages/runtime-core/src/apiNewDefineComponent.ts diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index b85e3b3b732..a62e1bdcf48 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -9,18 +9,58 @@ import { } from './componentOptions' import { SetupContext, - FunctionalComponent, AllowedComponentProps, ComponentCustomProps } from './component' -import { - CreateComponentPublicInstance, - ComponentPublicInstanceConstructor -} from './componentProxy' import { ExtractPropTypes, ComponentPropsOptions } from './componentProps' import { EmitsOptions } from './componentEmits' import { isFunction } from '@vue/shared' import { VNodeProps } from './vnode' +import { + CreateComponentPublicInstance, + ComponentPublicInstance +} from './componentProxy' + +declare const DefineComponent: unique symbol +declare const JSX: unique symbol + +export interface DefineComponentJSX { + [JSX]: true +} + +export type DefineComponent< + Props, + RawBindings, + D, + C extends ComputedOptions = {}, + M extends MethodOptions = {}, + Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, + Extends extends ComponentOptionsMixin = ComponentOptionsMixin, + E extends EmitsOptions = Record, + PublicProps = {} +> = CreateComponentPublicInstance< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + PublicProps +> & { [DefineComponent]: true } & DefineComponentJSX< + CreateComponentPublicInstance< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + PublicProps + > + > // defineComponent is a utility that is primarily used for type inference // when declaring components. Type inference is provided in the component @@ -34,21 +74,18 @@ export function defineComponent( props: Readonly, ctx: SetupContext ) => RawBindings | RenderFunction -): ComponentPublicInstanceConstructor< - CreateComponentPublicInstance< - Props, - RawBindings, - {}, - {}, - {}, - {}, - {}, - {}, - // public props - VNodeProps & Props & AllowedComponentProps & ComponentCustomProps - > -> & - FunctionalComponent +): DefineComponent< + Props, + RawBindings, + {}, + {}, + {}, + {}, + {}, + {}, + // public props + VNodeProps & Props & AllowedComponentProps & ComponentCustomProps +> // overload 2: object format with no props // (uses user defined props interface) @@ -75,30 +112,17 @@ export function defineComponent< E, EE > -): ComponentPublicInstanceConstructor< - CreateComponentPublicInstance< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - VNodeProps & Props & AllowedComponentProps & ComponentCustomProps - > -> & - ComponentOptionsWithoutProps< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE - > +): DefineComponent< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + VNodeProps & Props & AllowedComponentProps & ComponentCustomProps +> // overload 3: object format with array props declaration // props inferred as { [key in PropNames]?: any } @@ -125,32 +149,17 @@ export function defineComponent< E, EE > -): ComponentPublicInstanceConstructor< - // array props technically doesn't place any constraints on props in TSX before, - // but now we can export array props in TSX - CreateComponentPublicInstance< - Readonly<{ [key in PropNames]?: any }>, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - AllowedComponentProps & ComponentCustomProps - > -> & - ComponentOptionsWithArrayProps< - PropNames, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE - > +): DefineComponent< + Readonly<{ [key in PropNames]?: any }>, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + AllowedComponentProps & ComponentCustomProps +> // overload 4: object format with object props declaration // see `ExtractPropTypes` in ./componentProps.ts @@ -178,34 +187,19 @@ export function defineComponent< E, EE > -): ComponentPublicInstanceConstructor< - CreateComponentPublicInstance< - ExtractPropTypes, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - VNodeProps & AllowedComponentProps & ComponentCustomProps - > -> & - ComponentOptionsWithObjectProps< - PropsOptions, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE - > +): DefineComponent< + ExtractPropTypes, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + VNodeProps & AllowedComponentProps & ComponentCustomProps +> // implementation, close to no-op export function defineComponent(options: unknown) { - return isFunction(options) - ? { setup: options, name: options.name } - : options + return isFunction(options) ? { setup: options, name: options.name } : options } diff --git a/packages/runtime-core/src/apiNewDefineComponent.ts b/packages/runtime-core/src/apiNewDefineComponent.ts deleted file mode 100644 index ae0c4865edc..00000000000 --- a/packages/runtime-core/src/apiNewDefineComponent.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { - ComputedOptions, - MethodOptions, - ComponentOptionsWithoutProps, - ComponentOptionsWithArrayProps, - ComponentOptionsWithObjectProps, - ComponentOptionsMixin, - RenderFunction -} from './componentOptions' -import { - SetupContext, - AllowedComponentProps, - ComponentCustomProps -} from './component' -import { ExtractPropTypes, ComponentPropsOptions } from './componentProps' -import { EmitsOptions } from './componentEmits' -import { isFunction } from '@vue/shared' -import { VNodeProps } from './vnode' -import { - CreateComponentPublicInstance, - ComponentPublicInstance -} from './componentProxy' - -declare const DefineComponent: unique symbol -declare const JSX: unique symbol - -export interface DefineComponentJSX { - [JSX]: true -} - -export type DefineComponent< - Props, - RawBindings, - D, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, - Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, - Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = Record, - PublicProps = {} -> = CreateComponentPublicInstance< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - PublicProps -> & { [DefineComponent]: true } & DefineComponentJSX< - CreateComponentPublicInstance< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - PublicProps - > - > - -// newDefineComponent is a utility that is primarily used for type inference -// when declaring components. Type inference is provided in the component -// options (provided as the argument). The returned value has artificial types -// for TSX / manual render function / IDE support. - -// overload 1: direct setup function -// (uses user defined props interface) -export function newDefineComponent( - setup: ( - props: Readonly, - ctx: SetupContext - ) => RawBindings | RenderFunction -): DefineComponent< - Props, - RawBindings, - {}, - {}, - {}, - {}, - {}, - {}, - // public props - VNodeProps & Props & AllowedComponentProps & ComponentCustomProps -> - -// overload 2: object format with no props -// (uses user defined props interface) -// return type is for Vetur and TSX support -export function newDefineComponent< - Props = {}, - RawBindings = {}, - D = {}, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, - Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, - Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = Record, - EE extends string = string ->( - options: ComponentOptionsWithoutProps< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE - > -): DefineComponent< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - VNodeProps & Props & AllowedComponentProps & ComponentCustomProps -> - -// overload 3: object format with array props declaration -// props inferred as { [key in PropNames]?: any } -// return type is for Vetur and TSX support -export function newDefineComponent< - PropNames extends string, - RawBindings, - D, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, - Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, - Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = Record, - EE extends string = string ->( - options: ComponentOptionsWithArrayProps< - PropNames, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE - > -): DefineComponent< - Readonly<{ [key in PropNames]?: any }>, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - AllowedComponentProps & ComponentCustomProps -> - -// overload 4: object format with object props declaration -// see `ExtractPropTypes` in ./componentProps.ts -export function newDefineComponent< - // the Readonly constraint allows TS to treat the type of { required: true } - // as constant instead of boolean. - PropsOptions extends Readonly, - RawBindings, - D, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, - Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, - Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = Record, - EE extends string = string ->( - options: ComponentOptionsWithObjectProps< - PropsOptions, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE - > -): DefineComponent< - ExtractPropTypes, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - VNodeProps & AllowedComponentProps & ComponentCustomProps -> - -// implementation, close to no-op -export function newDefineComponent(options: unknown) { - return isFunction(options) ? { setup: options, name: options.name } : options -} diff --git a/packages/runtime-core/src/index.ts b/packages/runtime-core/src/index.ts index e22af985c61..fd3f57b0a85 100644 --- a/packages/runtime-core/src/index.ts +++ b/packages/runtime-core/src/index.ts @@ -41,12 +41,11 @@ export { } from './apiLifecycle' export { provide, inject } from './apiInject' export { nextTick } from './scheduler' -export { defineComponent } from './apiDefineComponent' export { - newDefineComponent, - DefineComponentJSX, - DefineComponent -} from './apiNewDefineComponent' + defineComponent, + DefineComponent, + DefineComponentJSX +} from './apiDefineComponent' export { defineAsyncComponent } from './apiAsyncComponent' // Advanced API ---------------------------------------------------------------- diff --git a/test-dts/defineComponent.test-d.tsx b/test-dts/defineComponent.test-d.tsx index f00d54bc317..435f3ca9cb0 100644 --- a/test-dts/defineComponent.test-d.tsx +++ b/test-dts/defineComponent.test-d.tsx @@ -743,31 +743,3 @@ describe('componentOptions setup should be `SetupContext`', () => { ctx: SetupContext ) => any) }) - -const Wprops = defineComponent({ - props: { - x1: { - type: String, - required: true - }, - x2: Number - } -}) - -const Xprops = newDefineComponent({ - props: { - x1: { - type: String, - required: true - }, - x2: Number - } -}) - -// @ts-expect-error -expectType() - -// @ts-expect-error -expectError() -// @ts-expect-error -expectError() From 5d92fa1c3b7800fee5f70f7b0cc5d760f8765827 Mon Sep 17 00:00:00 2001 From: pikax Date: Tue, 18 Aug 2020 09:04:21 +0100 Subject: [PATCH 04/24] chore: remove some old code --- .../runtime-core/src/apiDefineComponent.ts | 66 +++++++++++++++---- test-dts/componentTypeExtensions.test-d.tsx | 49 +------------- test-dts/defineComponent.test-d.tsx | 10 +-- 3 files changed, 55 insertions(+), 70 deletions(-) diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index a62e1bdcf48..0b9db254ffa 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -5,12 +5,14 @@ import { ComponentOptionsWithArrayProps, ComponentOptionsWithObjectProps, ComponentOptionsMixin, - RenderFunction + RenderFunction, + ComponentOptionsBase } from './componentOptions' import { SetupContext, AllowedComponentProps, - ComponentCustomProps + ComponentCustomProps, + ComponentOptions } from './component' import { ExtractPropTypes, ComponentPropsOptions } from './componentProps' import { EmitsOptions } from './componentEmits' @@ -29,6 +31,9 @@ export interface DefineComponentJSX { } export type DefineComponent< + Options extends + | ComponentOptions + | ComponentOptionsBase, Props, RawBindings, D, @@ -38,17 +43,18 @@ export type DefineComponent< Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = Record, PublicProps = {} -> = CreateComponentPublicInstance< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - PublicProps -> & { [DefineComponent]: true } & DefineComponentJSX< +> = Options & + CreateComponentPublicInstance< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + PublicProps + > & { [DefineComponent]: true } & DefineComponentJSX< CreateComponentPublicInstance< Props, RawBindings, @@ -75,6 +81,7 @@ export function defineComponent( ctx: SetupContext ) => RawBindings | RenderFunction ): DefineComponent< + any, Props, RawBindings, {}, @@ -113,6 +120,17 @@ export function defineComponent< EE > ): DefineComponent< + ComponentOptionsWithoutProps< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE + >, Props, RawBindings, D, @@ -150,6 +168,17 @@ export function defineComponent< EE > ): DefineComponent< + ComponentOptionsWithArrayProps< + PropNames, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE + >, Readonly<{ [key in PropNames]?: any }>, RawBindings, D, @@ -188,6 +217,17 @@ export function defineComponent< EE > ): DefineComponent< + ComponentOptionsWithObjectProps< + PropsOptions, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE + >, ExtractPropTypes, RawBindings, D, diff --git a/test-dts/componentTypeExtensions.test-d.tsx b/test-dts/componentTypeExtensions.test-d.tsx index 5e52310a344..32a72f844e6 100644 --- a/test-dts/componentTypeExtensions.test-d.tsx +++ b/test-dts/componentTypeExtensions.test-d.tsx @@ -1,9 +1,4 @@ -import { - defineComponent, - expectError, - expectType, - newDefineComponent -} from './index' +import { defineComponent, expectError, expectType } from './index' declare module '@vue/runtime-core' { interface ComponentCustomOptions { @@ -60,45 +55,3 @@ expectError() expectError() // @ts-expect-error expectError() - -const Custom2 = newDefineComponent({ - props: { - bar: String, - baz: { - type: Number, - required: true - } - }, - - data: () => ({ counter: 0 }), - - test(n) { - expectType(n) - }, - - methods: { - aMethod() { - // @ts-expect-error - expectError(this.notExisting) - this.counter++ - this.state = 'running' - // @ts-expect-error - expectError((this.state = 'not valid')) - } - } -}) - -expectType() -expectType() -expectType() - -// @ts-expect-error -expectType() -// @ts-expect-error -expectError() -// @ts-expect-error -expectError() -// @ts-expect-error -expectError() -// @ts-expect-error -expectError() diff --git a/test-dts/defineComponent.test-d.tsx b/test-dts/defineComponent.test-d.tsx index 435f3ca9cb0..b65ca88ae89 100644 --- a/test-dts/defineComponent.test-d.tsx +++ b/test-dts/defineComponent.test-d.tsx @@ -9,15 +9,7 @@ import { expectType, ComponentPublicInstance, ComponentOptions, - SetupContext, - FunctionalComponent, - h, - Component, - ComponentOptionsWithoutProps, - ComponentOptionsWithArrayProps, - ComponentOptionsWithObjectProps, - ComponentPropsOptions, - newDefineComponent + SetupContext } from './index' describe('with object props', () => { From d163f78669b4e333110ba6ff5e69b90d34eeb6df Mon Sep 17 00:00:00 2001 From: pikax Date: Tue, 18 Aug 2020 09:26:38 +0100 Subject: [PATCH 05/24] chore: working --- .../runtime-core/src/apiDefineComponent.ts | 20 +++---------------- packages/runtime-dom/types/jsx.d.ts | 12 +++++------ 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index 0b9db254ffa..f01e8839281 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -23,9 +23,7 @@ import { ComponentPublicInstance } from './componentProxy' -declare const DefineComponent: unique symbol declare const JSX: unique symbol - export interface DefineComponentJSX { [JSX]: true } @@ -42,9 +40,8 @@ export type DefineComponent< Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = Record, - PublicProps = {} -> = Options & - CreateComponentPublicInstance< + PublicProps = {}, + PublicInstance extends ComponentPublicInstance = CreateComponentPublicInstance< Props, RawBindings, D, @@ -54,19 +51,8 @@ export type DefineComponent< Extends, E, PublicProps - > & { [DefineComponent]: true } & DefineComponentJSX< - CreateComponentPublicInstance< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - PublicProps - > > +> = PublicInstance & Options & DefineComponentJSX // defineComponent is a utility that is primarily used for type inference // when declaring components. Type inference is provided in the component diff --git a/packages/runtime-dom/types/jsx.d.ts b/packages/runtime-dom/types/jsx.d.ts index 1273d575409..53bda63c205 100644 --- a/packages/runtime-dom/types/jsx.d.ts +++ b/packages/runtime-dom/types/jsx.d.ts @@ -1316,6 +1316,12 @@ type EventHandlers = { // named imports. import * as RuntimeCore from '@vue/runtime-core' +declare module '@vue/runtime-core/' { + interface DefineComponentJSX { + new (): T + } +} + type ReservedProps = { key?: string | number ref?: @@ -1352,9 +1358,3 @@ declare global { // suppress ts:2669 export {} - -declare module '@vue/runtime-core' { - interface DefineComponentJSX { - new (): T - } -} From 133d6b03378132904a474fd9f33146ee992246bd Mon Sep 17 00:00:00 2001 From: pikax Date: Tue, 18 Aug 2020 09:59:26 +0100 Subject: [PATCH 06/24] chore: more changes --- .../runtime-core/src/apiDefineComponent.ts | 93 ++++++++++--------- 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index f01e8839281..4ddefadbdd8 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -29,18 +29,27 @@ export interface DefineComponentJSX { } export type DefineComponent< - Options extends - | ComponentOptions - | ComponentOptionsBase, - Props, - RawBindings, - D, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, + Props = any, + RawBindings = any, + D = any, + C extends ComputedOptions = ComputedOptions, + M extends MethodOptions = MethodOptions, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = Record, - PublicProps = {}, + PublicProps = any, + Options extends + | ComponentOptions + | ComponentOptionsBase< + any, + any, + any, + any, + any, + any, + any, + any + > = ComponentOptions, PublicInstance extends ComponentPublicInstance = CreateComponentPublicInstance< Props, RawBindings, @@ -52,7 +61,7 @@ export type DefineComponent< E, PublicProps > -> = PublicInstance & Options & DefineComponentJSX +> = Options & DefineComponentJSX // defineComponent is a utility that is primarily used for type inference // when declaring components. Type inference is provided in the component @@ -67,7 +76,6 @@ export function defineComponent( ctx: SetupContext ) => RawBindings | RenderFunction ): DefineComponent< - any, Props, RawBindings, {}, @@ -77,7 +85,8 @@ export function defineComponent( {}, {}, // public props - VNodeProps & Props & AllowedComponentProps & ComponentCustomProps + VNodeProps & Props & AllowedComponentProps & ComponentCustomProps, + ComponentOptions > // overload 2: object format with no props @@ -106,6 +115,15 @@ export function defineComponent< EE > ): DefineComponent< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + VNodeProps & Props & AllowedComponentProps & ComponentCustomProps, ComponentOptionsWithoutProps< Props, RawBindings, @@ -116,16 +134,7 @@ export function defineComponent< Extends, E, EE - >, - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - VNodeProps & Props & AllowedComponentProps & ComponentCustomProps + > > // overload 3: object format with array props declaration @@ -154,6 +163,15 @@ export function defineComponent< EE > ): DefineComponent< + Readonly<{ [key in PropNames]?: any }>, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + AllowedComponentProps & ComponentCustomProps, ComponentOptionsWithArrayProps< PropNames, RawBindings, @@ -164,16 +182,7 @@ export function defineComponent< Extends, E, EE - >, - Readonly<{ [key in PropNames]?: any }>, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - AllowedComponentProps & ComponentCustomProps + > > // overload 4: object format with object props declaration @@ -203,6 +212,15 @@ export function defineComponent< EE > ): DefineComponent< + ExtractPropTypes, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + VNodeProps & AllowedComponentProps & ComponentCustomProps, ComponentOptionsWithObjectProps< PropsOptions, RawBindings, @@ -213,16 +231,7 @@ export function defineComponent< Extends, E, EE - >, - ExtractPropTypes, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - VNodeProps & AllowedComponentProps & ComponentCustomProps + > > // implementation, close to no-op From b07f54de2d2b3983e2b33a326888bcfeade29d1e Mon Sep 17 00:00:00 2001 From: pikax Date: Tue, 18 Aug 2020 10:13:17 +0100 Subject: [PATCH 07/24] chore: reducing code and types --- .../runtime-core/src/apiDefineComponent.ts | 120 +++++------------- packages/runtime-core/src/component.ts | 2 +- 2 files changed, 32 insertions(+), 90 deletions(-) diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index 4ddefadbdd8..03c4d00afc8 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -11,8 +11,7 @@ import { import { SetupContext, AllowedComponentProps, - ComponentCustomProps, - ComponentOptions + ComponentCustomProps } from './component' import { ExtractPropTypes, ComponentPropsOptions } from './componentProps' import { EmitsOptions } from './componentEmits' @@ -28,6 +27,11 @@ export interface DefineComponentJSX { [JSX]: true } +export type PublicProps = VNodeProps & + Props & + AllowedComponentProps & + ComponentCustomProps + export type DefineComponent< Props = any, RawBindings = any, @@ -37,31 +41,24 @@ export type DefineComponent< Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = Record, - PublicProps = any, - Options extends - | ComponentOptions - | ComponentOptionsBase< - any, - any, - any, - any, - any, - any, - any, - any - > = ComponentOptions, - PublicInstance extends ComponentPublicInstance = CreateComponentPublicInstance< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - PublicProps - > -> = Options & DefineComponentJSX + EE extends string = string, + PP = PublicProps +> = ComponentOptionsBase & + DefineComponentJSX< + CreateComponentPublicInstance< + Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + PP + > + > & + PP +// public props // defineComponent is a utility that is primarily used for type inference // when declaring components. Type inference is provided in the component @@ -75,19 +72,7 @@ export function defineComponent( props: Readonly, ctx: SetupContext ) => RawBindings | RenderFunction -): DefineComponent< - Props, - RawBindings, - {}, - {}, - {}, - {}, - {}, - {}, - // public props - VNodeProps & Props & AllowedComponentProps & ComponentCustomProps, - ComponentOptions -> +): DefineComponent // overload 2: object format with no props // (uses user defined props interface) @@ -96,11 +81,11 @@ export function defineComponent< Props = {}, RawBindings = {}, D = {}, - C extends ComputedOptions = {}, - M extends MethodOptions = {}, + C extends ComputedOptions = ComputedOptions, + M extends MethodOptions = MethodOptions, Mixin extends ComponentOptionsMixin = ComponentOptionsMixin, Extends extends ComponentOptionsMixin = ComponentOptionsMixin, - E extends EmitsOptions = Record, + E extends EmitsOptions = EmitsOptions, EE extends string = string >( options: ComponentOptionsWithoutProps< @@ -114,28 +99,7 @@ export function defineComponent< E, EE > -): DefineComponent< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - VNodeProps & Props & AllowedComponentProps & ComponentCustomProps, - ComponentOptionsWithoutProps< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE - > -> +): DefineComponent // overload 3: object format with array props declaration // props inferred as { [key in PropNames]?: any } @@ -171,18 +135,7 @@ export function defineComponent< Mixin, Extends, E, - AllowedComponentProps & ComponentCustomProps, - ComponentOptionsWithArrayProps< - PropNames, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE - > + EE > // overload 4: object format with object props declaration @@ -220,18 +173,7 @@ export function defineComponent< Mixin, Extends, E, - VNodeProps & AllowedComponentProps & ComponentCustomProps, - ComponentOptionsWithObjectProps< - PropsOptions, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE - > + EE > // implementation, close to no-op diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 12eaa76bc93..c7ea3b9da27 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -110,7 +110,7 @@ export interface ClassComponent { __vccOpts: ComponentOptions } -export type Component = ComponentOptions | FunctionalComponent +export type Component = ComponentOptions | FunctionalComponent // A type used in public APIs where a component type is expected. // The constructor type is an artificial type returned by defineComponent(). From d5968eae77c2e914743b8b9b352e24a3fdc67219 Mon Sep 17 00:00:00 2001 From: pikax Date: Tue, 18 Aug 2020 10:30:32 +0100 Subject: [PATCH 08/24] wip --- packages/runtime-core/src/apiDefineComponent.ts | 2 +- test-dts/defineComponent.test-d.tsx | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index 03c4d00afc8..58fd8022a3d 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -165,7 +165,7 @@ export function defineComponent< EE > ): DefineComponent< - ExtractPropTypes, + Readonly>, RawBindings, D, C, diff --git a/test-dts/defineComponent.test-d.tsx b/test-dts/defineComponent.test-d.tsx index b65ca88ae89..250b6531e49 100644 --- a/test-dts/defineComponent.test-d.tsx +++ b/test-dts/defineComponent.test-d.tsx @@ -357,6 +357,9 @@ describe('with mixins', () => { } } }) + + expectType(MixinA.aP1) + const MixinB = defineComponent({ props: ['bP1', 'bP2'], data() { From cf809a4fe9d41df1cc6985d99c5f9894ad2613ca Mon Sep 17 00:00:00 2001 From: pikax Date: Tue, 18 Aug 2020 11:04:17 +0100 Subject: [PATCH 09/24] chore: improvements --- .../runtime-core/src/apiDefineComponent.ts | 54 +++++++++---------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index 58fd8022a3d..571a0b621ee 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -27,13 +27,12 @@ export interface DefineComponentJSX { [JSX]: true } -export type PublicProps = VNodeProps & - Props & +export type PublicProps = VNodeProps & AllowedComponentProps & ComponentCustomProps export type DefineComponent< - Props = any, + PropsOrPropOptions = any, RawBindings = any, D = any, C extends ComputedOptions = ComputedOptions, @@ -42,23 +41,28 @@ export type DefineComponent< Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = Record, EE extends string = string, - PP = PublicProps -> = ComponentOptionsBase & - DefineComponentJSX< - CreateComponentPublicInstance< - Props, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - PP - > - > & + // extract currect options + Props = PropsOrPropOptions extends ComponentPropsOptions + ? Readonly> + : PropsOrPropOptions, + PP = PublicProps +> = DefineComponentJSX< + CreateComponentPublicInstance< + PropsOrPropOptions extends ComponentPropsOptions + ? Readonly> + : Props, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + PP + > +> & + ComponentOptionsBase & PP -// public props // defineComponent is a utility that is primarily used for type inference // when declaring components. Type inference is provided in the component @@ -164,17 +168,7 @@ export function defineComponent< E, EE > -): DefineComponent< - Readonly>, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - EE -> +): DefineComponent // implementation, close to no-op export function defineComponent(options: unknown) { From 0c7c24e1a4e068e6b4e63fd7f1b0fcbb52230594 Mon Sep 17 00:00:00 2001 From: pikax Date: Tue, 18 Aug 2020 13:02:46 +0100 Subject: [PATCH 10/24] chore: working --- .../runtime-core/src/apiDefineComponent.ts | 34 +++++++++++++------ packages/runtime-core/src/h.ts | 11 +++++- test-dts/h.test-d.ts | 2 ++ 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index 571a0b621ee..354bf57c626 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -23,7 +23,9 @@ import { } from './componentProxy' declare const JSX: unique symbol -export interface DefineComponentJSX { +export interface DefineComponentJSX< + T extends ComponentPublicInstance = ComponentPublicInstance +> { [JSX]: true } @@ -41,16 +43,16 @@ export type DefineComponent< Extends extends ComponentOptionsMixin = ComponentOptionsMixin, E extends EmitsOptions = Record, EE extends string = string, - // extract currect options - Props = PropsOrPropOptions extends ComponentPropsOptions - ? Readonly> - : PropsOrPropOptions, - PP = PublicProps + PP = PublicProps, + RequiredProps = PropsOrPropOptions extends string + ? Readonly<{ [K in PropsOrPropOptions]?: any }> + : Readonly>, + OptionalProps = PropsOrPropOptions extends string + ? Readonly<{ [K in PropsOrPropOptions]?: any }> + : Readonly> > = DefineComponentJSX< CreateComponentPublicInstance< - PropsOrPropOptions extends ComponentPropsOptions - ? Readonly> - : Props, + OptionalProps, RawBindings, D, C, @@ -58,10 +60,20 @@ export type DefineComponent< Mixin, Extends, E, - PP + PP & OptionalProps > > & - ComponentOptionsBase & + ComponentOptionsBase< + RequiredProps, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + EE + > & PP // defineComponent is a utility that is primarily used for type inference diff --git a/packages/runtime-core/src/h.ts b/packages/runtime-core/src/h.ts index 42d9c971438..3d3e9824e3d 100644 --- a/packages/runtime-core/src/h.ts +++ b/packages/runtime-core/src/h.ts @@ -13,6 +13,7 @@ import { RawSlots } from './componentSlots' import { FunctionalComponent, Component } from './component' import { ComponentOptions } from './componentOptions' import { EmitsOptions } from './componentEmits' +import { DefineComponent } from './apiDefineComponent' // `h` is a more user-friendly version of `createVNode` that allows omitting the // props when possible. It is intended for manually written render functions. @@ -50,7 +51,7 @@ type RawProps = VNodeProps & { __v_isVNode?: never // used to differ from Array children [Symbol.iterator]?: never -} & { [key: string]: any } +} & Record type RawChildren = | string @@ -124,6 +125,14 @@ export function h>( children?: RawChildren | RawSlots ): VNode +// fake constructor type returned by `defineComponent` +export function h(type: DefineComponent, children?: RawChildren): VNode +export function h

( + type: DefineComponent

, + props: (RawProps & P) | ({} extends P ? null : never), + children?: RawChildren | RawSlots +): VNode + // fake constructor type returned by `defineComponent` or class component export function h(type: Constructor, children?: RawChildren): VNode export function h

( diff --git a/test-dts/h.test-d.ts b/test-dts/h.test-d.ts index b4dc19bb4d5..49604e84051 100644 --- a/test-dts/h.test-d.ts +++ b/test-dts/h.test-d.ts @@ -99,6 +99,8 @@ describe('h inference w/ defineComponent', () => { } }) + new Foo().$props.bar + h(Foo, { bar: 1 }) h(Foo, { bar: 1, foo: 'ok' }) // should allow extraneous props (attrs fallthrough) From 30c7351173e255e1ed6cc5a256307a619ea75eab Mon Sep 17 00:00:00 2001 From: pikax Date: Tue, 18 Aug 2020 13:25:14 +0100 Subject: [PATCH 11/24] chore: remove unnecessary code --- packages/runtime-core/src/apiDefineComponent.ts | 8 ++------ packages/runtime-core/src/h.ts | 15 +++++++-------- test-dts/defineComponent.test-d.tsx | 3 --- test-dts/h.test-d.ts | 2 -- 4 files changed, 9 insertions(+), 19 deletions(-) diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index 354bf57c626..7f9c2a13085 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -44,12 +44,8 @@ export type DefineComponent< E extends EmitsOptions = Record, EE extends string = string, PP = PublicProps, - RequiredProps = PropsOrPropOptions extends string - ? Readonly<{ [K in PropsOrPropOptions]?: any }> - : Readonly>, - OptionalProps = PropsOrPropOptions extends string - ? Readonly<{ [K in PropsOrPropOptions]?: any }> - : Readonly> + RequiredProps = Readonly>, + OptionalProps = Readonly> > = DefineComponentJSX< CreateComponentPublicInstance< OptionalProps, diff --git a/packages/runtime-core/src/h.ts b/packages/runtime-core/src/h.ts index 3d3e9824e3d..3e94abc473b 100644 --- a/packages/runtime-core/src/h.ts +++ b/packages/runtime-core/src/h.ts @@ -13,7 +13,6 @@ import { RawSlots } from './componentSlots' import { FunctionalComponent, Component } from './component' import { ComponentOptions } from './componentOptions' import { EmitsOptions } from './componentEmits' -import { DefineComponent } from './apiDefineComponent' // `h` is a more user-friendly version of `createVNode` that allows omitting the // props when possible. It is intended for manually written render functions. @@ -125,13 +124,13 @@ export function h>( children?: RawChildren | RawSlots ): VNode -// fake constructor type returned by `defineComponent` -export function h(type: DefineComponent, children?: RawChildren): VNode -export function h

( - type: DefineComponent

, - props: (RawProps & P) | ({} extends P ? null : never), - children?: RawChildren | RawSlots -): VNode +// // fake constructor type returned by `defineComponent` +// export function h(type: DefineComponent, children?: RawChildren): VNode +// export function h

( +// type: DefineComponent

, +// props: (RawProps & P) | ({} extends P ? null : never), +// children?: RawChildren | RawSlots +// ): VNode // fake constructor type returned by `defineComponent` or class component export function h(type: Constructor, children?: RawChildren): VNode diff --git a/test-dts/defineComponent.test-d.tsx b/test-dts/defineComponent.test-d.tsx index 250b6531e49..b65ca88ae89 100644 --- a/test-dts/defineComponent.test-d.tsx +++ b/test-dts/defineComponent.test-d.tsx @@ -357,9 +357,6 @@ describe('with mixins', () => { } } }) - - expectType(MixinA.aP1) - const MixinB = defineComponent({ props: ['bP1', 'bP2'], data() { diff --git a/test-dts/h.test-d.ts b/test-dts/h.test-d.ts index 49604e84051..b4dc19bb4d5 100644 --- a/test-dts/h.test-d.ts +++ b/test-dts/h.test-d.ts @@ -99,8 +99,6 @@ describe('h inference w/ defineComponent', () => { } }) - new Foo().$props.bar - h(Foo, { bar: 1 }) h(Foo, { bar: 1, foo: 'ok' }) // should allow extraneous props (attrs fallthrough) From c2fd006e5270a5819c66211cb459e778d7901f88 Mon Sep 17 00:00:00 2001 From: pikax Date: Tue, 18 Aug 2020 13:31:36 +0100 Subject: [PATCH 12/24] chore: remove commented code --- packages/runtime-core/src/h.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/runtime-core/src/h.ts b/packages/runtime-core/src/h.ts index 3e94abc473b..7bad965d217 100644 --- a/packages/runtime-core/src/h.ts +++ b/packages/runtime-core/src/h.ts @@ -124,14 +124,6 @@ export function h>( children?: RawChildren | RawSlots ): VNode -// // fake constructor type returned by `defineComponent` -// export function h(type: DefineComponent, children?: RawChildren): VNode -// export function h

( -// type: DefineComponent

, -// props: (RawProps & P) | ({} extends P ? null : never), -// children?: RawChildren | RawSlots -// ): VNode - // fake constructor type returned by `defineComponent` or class component export function h(type: Constructor, children?: RawChildren): VNode export function h

( From 685ef7fee6c250fe3b14a5ee43f60ee1570bf7c6 Mon Sep 17 00:00:00 2001 From: pikax Date: Tue, 18 Aug 2020 14:07:01 +0100 Subject: [PATCH 13/24] chore: readd h defineComponent overload --- packages/runtime-core/src/h.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/runtime-core/src/h.ts b/packages/runtime-core/src/h.ts index 7bad965d217..ce1c3507e7e 100644 --- a/packages/runtime-core/src/h.ts +++ b/packages/runtime-core/src/h.ts @@ -13,6 +13,7 @@ import { RawSlots } from './componentSlots' import { FunctionalComponent, Component } from './component' import { ComponentOptions } from './componentOptions' import { EmitsOptions } from './componentEmits' +import { DefineComponent } from './apiDefineComponent' // `h` is a more user-friendly version of `createVNode` that allows omitting the // props when possible. It is intended for manually written render functions. @@ -131,6 +132,13 @@ export function h

( props?: (RawProps & P) | ({} extends P ? null : never), children?: RawChildren | RawSlots ): VNode +// fake constructor type returned by `defineComponent` +export function h(type: DefineComponent, children?: RawChildren): VNode +export function h

( + type: DefineComponent

, + props: (RawProps & P) | ({} extends P ? null : never), + children?: RawChildren | RawSlots +): VNode // Actual implementation export function h(type: any, propsOrChildren?: any, children?: any): VNode { From 3548497b69c5f75a8e2089ea31bdb5d28ec765d8 Mon Sep 17 00:00:00 2001 From: pikax Date: Tue, 18 Aug 2020 14:11:32 +0100 Subject: [PATCH 14/24] chore: from jsx contructor --- packages/runtime-core/src/apiDefineComponent.ts | 2 +- packages/runtime-dom/types/jsx.d.ts | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index 7f9c2a13085..b299ba8fa8c 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -26,7 +26,7 @@ declare const JSX: unique symbol export interface DefineComponentJSX< T extends ComponentPublicInstance = ComponentPublicInstance > { - [JSX]: true + new (): T } export type PublicProps = VNodeProps & diff --git a/packages/runtime-dom/types/jsx.d.ts b/packages/runtime-dom/types/jsx.d.ts index 53bda63c205..82a3ab851df 100644 --- a/packages/runtime-dom/types/jsx.d.ts +++ b/packages/runtime-dom/types/jsx.d.ts @@ -1316,12 +1316,6 @@ type EventHandlers = { // named imports. import * as RuntimeCore from '@vue/runtime-core' -declare module '@vue/runtime-core/' { - interface DefineComponentJSX { - new (): T - } -} - type ReservedProps = { key?: string | number ref?: From d8e9a12d3dc9565c569016b0771cb939381dea66 Mon Sep 17 00:00:00 2001 From: pikax Date: Thu, 20 Aug 2020 08:14:50 +0100 Subject: [PATCH 15/24] chore: remove unuse symbol --- packages/runtime-core/src/apiDefineComponent.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/runtime-core/src/apiDefineComponent.ts b/packages/runtime-core/src/apiDefineComponent.ts index b299ba8fa8c..60b92adaae0 100644 --- a/packages/runtime-core/src/apiDefineComponent.ts +++ b/packages/runtime-core/src/apiDefineComponent.ts @@ -22,7 +22,6 @@ import { ComponentPublicInstance } from './componentProxy' -declare const JSX: unique symbol export interface DefineComponentJSX< T extends ComponentPublicInstance = ComponentPublicInstance > { From dc9db23ba142c746a940d305df991ddc170a7ba7 Mon Sep 17 00:00:00 2001 From: pikax Date: Thu, 20 Aug 2020 08:37:15 +0100 Subject: [PATCH 16/24] chore: fix h overload --- packages/runtime-core/src/h.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/runtime-core/src/h.ts b/packages/runtime-core/src/h.ts index 732719de0ee..2613c9d452c 100644 --- a/packages/runtime-core/src/h.ts +++ b/packages/runtime-core/src/h.ts @@ -11,7 +11,7 @@ import { Suspense, SuspenseProps } from './components/Suspense' import { isObject, isArray } from '@vue/shared' import { RawSlots } from './componentSlots' import { FunctionalComponent, Component } from './component' -import { ComponentOptions } from './componentOptions' +import { ComponentOptionsBase } from './componentOptions' import { EmitsOptions } from './componentEmits' import { DefineComponent } from './apiDefineComponent' @@ -114,9 +114,14 @@ export function h( export function h(type: Component, children?: RawChildren): VNode // exclude `defineComponent` constructors -export function h>( +export function h< + T extends + | ComponentOptionsBase + | FunctionalComponent, + P +>( type: T, - props?: RawProps | null, + props: (RawProps & P) | ({} extends P ? null : never), children?: RawChildren | RawSlots ): VNode From f96a16d7b41f4a9ca7b43ed28d6135b5548ae810 Mon Sep 17 00:00:00 2001 From: pikax Date: Thu, 20 Aug 2020 10:13:15 +0100 Subject: [PATCH 17/24] chore: improve Component type and allow to infer Props/RawBinding --- packages/runtime-core/src/component.ts | 27 +- packages/runtime-core/src/componentOptions.ts | 11 +- .../src/componentPublicInstance.ts | 13 +- packages/runtime-core/src/h.ts | 7 +- test-dts/component.test-d.ts | 403 ++++++++++++++++++ 5 files changed, 448 insertions(+), 13 deletions(-) create mode 100644 test-dts/component.test-d.ts diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 8f770f5a23b..5f19e1e40bb 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -25,7 +25,12 @@ import { warn } from './warning' import { ErrorCodes, callWithErrorHandling } from './errorHandling' import { AppContext, createAppContext, AppConfig } from './apiCreateApp' import { validateDirectiveName } from './directives' -import { applyOptions, ComponentOptions } from './componentOptions' +import { + applyOptions, + ComponentOptions, + ComputedOptions, + MethodOptions +} from './componentOptions' import { EmitsOptions, ObjectEmitsOptions, @@ -116,13 +121,29 @@ export interface ClassComponent { * values, e.g. checking if its a function or not. This is mostly for internal * implementation code. */ -export type ConcreteComponent = ComponentOptions | FunctionalComponent +export type ConcreteComponent< + Props = any, + RawBindings = any, + D = any, + C extends ComputedOptions = ComputedOptions, + M extends MethodOptions = MethodOptions +> = + | ComponentOptions + | FunctionalComponent /** * A type used in public APIs where a component type is expected. * The constructor type is an artificial type returned by defineComponent(). */ -export type Component = ConcreteComponent | ComponentPublicInstanceConstructor +export type Component< + Props = any, + RawBindings = any, + D = any, + C extends ComputedOptions = ComputedOptions, + M extends MethodOptions = MethodOptions +> = + | ConcreteComponent + | ComponentPublicInstanceConstructor // TODO infer types export { ComponentOptions } diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index bb7a32ecef2..0b94cf180a3 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -231,10 +231,13 @@ export type ComponentOptionsWithObjectProps< > > -export type ComponentOptions = - | ComponentOptionsWithoutProps - | ComponentOptionsWithObjectProps - | ComponentOptionsWithArrayProps +export type ComponentOptions< + Props = any, + RawBindings = any, + D = any, + C extends ComputedOptions = ComputedOptions, + M extends MethodOptions = MethodOptions +> = ComponentOptionsBase export type ComponentOptionsMixin = ComponentOptionsBase< any, diff --git a/packages/runtime-core/src/componentPublicInstance.ts b/packages/runtime-core/src/componentPublicInstance.ts index 2205e1ae484..467ef3b514c 100644 --- a/packages/runtime-core/src/componentPublicInstance.ts +++ b/packages/runtime-core/src/componentPublicInstance.ts @@ -102,7 +102,18 @@ type UnwrapMixinsType< type EnsureNonVoid = T extends void ? {} : T export type ComponentPublicInstanceConstructor< - T extends ComponentPublicInstance = ComponentPublicInstance + T extends ComponentPublicInstance< + Props, + RawBindings, + D, + C, + M + > = ComponentPublicInstance, + Props = any, + RawBindings = any, + D = any, + C extends ComputedOptions = ComputedOptions, + M extends MethodOptions = MethodOptions > = { __isFragment?: never __isTeleport?: never diff --git a/packages/runtime-core/src/h.ts b/packages/runtime-core/src/h.ts index 2613c9d452c..86e0d86cc3a 100644 --- a/packages/runtime-core/src/h.ts +++ b/packages/runtime-core/src/h.ts @@ -10,8 +10,7 @@ import { Teleport, TeleportProps } from './components/Teleport' import { Suspense, SuspenseProps } from './components/Suspense' import { isObject, isArray } from '@vue/shared' import { RawSlots } from './componentSlots' -import { FunctionalComponent, Component } from './component' -import { ComponentOptionsBase } from './componentOptions' +import { FunctionalComponent, Component, ComponentOptions } from './component' import { EmitsOptions } from './componentEmits' import { DefineComponent } from './apiDefineComponent' @@ -115,9 +114,7 @@ export function h(type: Component, children?: RawChildren): VNode // exclude `defineComponent` constructors export function h< - T extends - | ComponentOptionsBase - | FunctionalComponent, + T extends ComponentOptions

| FunctionalComponent, P >( type: T, diff --git a/test-dts/component.test-d.ts b/test-dts/component.test-d.ts new file mode 100644 index 00000000000..6addd922175 --- /dev/null +++ b/test-dts/component.test-d.ts @@ -0,0 +1,403 @@ +import { + describe, + Component, + defineComponent, + PropType, + ref, + Ref, + expectError, + expectType, + ShallowUnwrapRef, + FunctionalComponent +} from './index' + +declare function extractComponentOptions( + obj: Component +): { + props: Props + rawBindings: RawBindings + setup: ShallowUnwrapRef +} + +describe('object props', () => { + interface ExpectedProps { + a?: number | undefined + b: string + e?: Function + bb: string + bbb: string + cc?: string[] | undefined + dd: { n: 1 } + ee?: () => string + ff?: (a: number, b: string) => { a: boolean } + ccc?: string[] | undefined + ddd: string[] + eee: () => { a: string } + fff: (a: number, b: string) => { a: boolean } + hhh: boolean + ggg: 'foo' | 'bar' + ffff: (a: number, b: string) => { a: boolean } + validated?: string + } + describe('defineComponent', () => { + const MyComponent = defineComponent({ + props: { + a: Number, + // required should make property non-void + b: { + type: String, + required: true + }, + e: Function, + // default value should infer type and make it non-void + bb: { + default: 'hello' + }, + bbb: { + // Note: default function value requires arrow syntax + explicit + // annotation + default: (props: any) => (props.bb as string) || 'foo' + }, + // explicit type casting + cc: Array as PropType, + // required + type casting + dd: { + type: Object as PropType<{ n: 1 }>, + required: true + }, + // return type + ee: Function as PropType<() => string>, + // arguments + object return + ff: Function as PropType<(a: number, b: string) => { a: boolean }>, + // explicit type casting with constructor + ccc: Array as () => string[], + // required + contructor type casting + ddd: { + type: Array as () => string[], + required: true + }, + // required + object return + eee: { + type: Function as PropType<() => { a: string }>, + required: true + }, + // required + arguments + object return + fff: { + type: Function as PropType<(a: number, b: string) => { a: boolean }>, + required: true + }, + hhh: { + type: Boolean, + required: true + }, + // default + type casting + ggg: { + type: String as PropType<'foo' | 'bar'>, + default: 'foo' + }, + // default + function + ffff: { + type: Function as PropType<(a: number, b: string) => { a: boolean }>, + default: (a: number, b: string) => ({ a: true }) + }, + validated: { + type: String, + // validator requires explicit annotation + validator: (val: unknown) => val !== '' + } + }, + setup(props) { + return { + setupA: 1, + setupB: ref(1), + setupC: { + a: ref(2) + }, + setupProps: props + } + } + }) + + const { props, rawBindings, setup } = extractComponentOptions(MyComponent) + + // props + expectType(props.a) + expectType(props.b) + expectType(props.e) + expectType(props.bb) + expectType(props.bbb) + expectType(props.cc) + expectType(props.dd) + expectType(props.ee) + expectType(props.ff) + expectType(props.ccc) + expectType(props.ddd) + expectType(props.eee) + expectType(props.fff) + expectType(props.hhh) + expectType(props.ggg) + expectType(props.ffff) + expectType(props.validated) + + // raw bindings + expectType(rawBindings.setupA) + expectType>(rawBindings.setupB) + expectType>(rawBindings.setupC.a) + expectType(rawBindings.setupA) + + // raw bindings props + expectType(rawBindings.setupProps.a) + expectType(rawBindings.setupProps.b) + expectType(rawBindings.setupProps.e) + expectType(rawBindings.setupProps.bb) + expectType(rawBindings.setupProps.bbb) + expectType(rawBindings.setupProps.cc) + expectType(rawBindings.setupProps.dd) + expectType(rawBindings.setupProps.ee) + expectType(rawBindings.setupProps.ff) + expectType(rawBindings.setupProps.ccc) + expectType(rawBindings.setupProps.ddd) + expectType(rawBindings.setupProps.eee) + expectType(rawBindings.setupProps.fff) + expectType(rawBindings.setupProps.hhh) + expectType(rawBindings.setupProps.ggg) + expectType(rawBindings.setupProps.ffff) + expectType(rawBindings.setupProps.validated) + + // setup + expectType(setup.setupA) + expectType(setup.setupB) + expectType>(setup.setupC.a) + expectType(setup.setupA) + + // raw bindings props + expectType(setup.setupProps.a) + expectType(setup.setupProps.b) + expectType(setup.setupProps.e) + expectType(setup.setupProps.bb) + expectType(setup.setupProps.bbb) + expectType(setup.setupProps.cc) + expectType(setup.setupProps.dd) + expectType(setup.setupProps.ee) + expectType(setup.setupProps.ff) + expectType(setup.setupProps.ccc) + expectType(setup.setupProps.ddd) + expectType(setup.setupProps.eee) + expectType(setup.setupProps.fff) + expectType(setup.setupProps.hhh) + expectType(setup.setupProps.ggg) + expectType(setup.setupProps.ffff) + expectType(setup.setupProps.validated) + }) + + describe('options', () => { + const MyComponent = { + props: { + a: Number, + // required should make property non-void + b: { + type: String, + required: true + }, + e: Function, + // default value should infer type and make it non-void + bb: { + default: 'hello' + }, + bbb: { + // Note: default function value requires arrow syntax + explicit + // annotation + default: (props: any) => (props.bb as string) || 'foo' + }, + // explicit type casting + cc: Array as PropType, + // required + type casting + dd: { + type: Object as PropType<{ n: 1 }>, + required: true + }, + // return type + ee: Function as PropType<() => string>, + // arguments + object return + ff: Function as PropType<(a: number, b: string) => { a: boolean }>, + // explicit type casting with constructor + ccc: Array as () => string[], + // required + contructor type casting + ddd: { + type: Array as () => string[], + required: true + }, + // required + object return + eee: { + type: Function as PropType<() => { a: string }>, + required: true + }, + // required + arguments + object return + fff: { + type: Function as PropType<(a: number, b: string) => { a: boolean }>, + required: true + }, + hhh: { + type: Boolean, + required: true + }, + // default + type casting + ggg: { + type: String as PropType<'foo' | 'bar'>, + default: 'foo' + }, + // default + function + ffff: { + type: Function as PropType<(a: number, b: string) => { a: boolean }>, + default: (a: number, b: string) => ({ a: true }) + }, + validated: { + type: String, + // validator requires explicit annotation + validator: (val: unknown) => val !== '' + } + }, + + setup() { + return { + setupA: 1 + } + } + } as const + + const { props, rawBindings, setup } = extractComponentOptions(MyComponent) + + // props + expectType(props.a) + expectType(props.b) + expectType(props.e) + expectType(props.bb) + expectType(props.bbb) + expectType(props.cc) + expectType(props.dd) + expectType(props.ee) + expectType(props.ff) + expectType(props.ccc) + expectType(props.ddd) + expectType(props.eee) + expectType(props.fff) + expectType(props.hhh) + expectType(props.ggg) + // expectType(props.ffff) // todo fix + expectType(props.validated) + + // rawBindings + expectType(rawBindings.setupA) + + //setup + expectType(setup.setupA) + }) +}) + +describe('array props', () => { + describe('defineComponent', () => { + const MyComponent = defineComponent({ + props: ['a', 'b'], + setup() { + return { + c: 1 + } + } + }) + + const { props, rawBindings, setup } = extractComponentOptions(MyComponent) + + // @ts-expect-error props should be readonly + expectError((props.a = 1)) + expectType(props.a) + expectType(props.b) + + expectType(rawBindings.c) + expectType(setup.c) + }) + + describe('options', () => { + const MyComponent = { + props: ['a', 'b'] as const, + setup() { + return { + c: 1 + } + } + } + + const { props, rawBindings, setup } = extractComponentOptions(MyComponent) + + // @ts-expect-error props should be readonly + expectError((props.a = 1)) + + // TODO infer the correct keys + // expectType(props.a) + // expectType(props.b) + + expectType(rawBindings.c) + expectType(setup.c) + }) +}) + +describe('no props', () => { + describe('defineComponent', () => { + const MyComponent = defineComponent({ + setup() { + return { + setupA: 1 + } + } + }) + + const { rawBindings, setup } = extractComponentOptions(MyComponent) + + expectType(rawBindings.setupA) + expectType(setup.setupA) + }) + + describe('options', () => { + const MyComponent = { + setup() { + return { + setupA: 1 + } + } + } + + const { rawBindings, setup } = extractComponentOptions(MyComponent) + + expectType(rawBindings.setupA) + expectType(setup.setupA) + }) +}) + +describe('functional', () => { + // TODO `props.foo` is `number|undefined` + // describe('defineComponent', () => { + // const MyComponent = defineComponent((props: { foo: number }) => {}) + + // const { props } = extractComponentOptions(MyComponent) + + // expectType(props.foo) + // }) + + describe('function', () => { + const MyComponent = (props: { foo: number }) => props.foo + const { props } = extractComponentOptions(MyComponent) + + expectType(props.foo) + }) + + describe('typed', () => { + const MyComponent: FunctionalComponent<{ foo: number }> = (_, _2) => {} + + const { props } = extractComponentOptions(MyComponent) + + expectType(props.foo) + }) +}) + +describe('class', () => { + // TODO +}) From a87e2e958de213eb1e9a696f48432e530ce760e0 Mon Sep 17 00:00:00 2001 From: pikax Date: Thu, 20 Aug 2020 11:29:54 +0100 Subject: [PATCH 18/24] chore: fixed errors? --- packages/runtime-core/src/component.ts | 6 +++--- packages/runtime-core/src/componentOptions.ts | 2 +- packages/runtime-core/src/h.ts | 19 ++++++++++++------- test-dts/component.test-d.ts | 13 +++++++++++-- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 5f19e1e40bb..4c97a34ac7e 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -122,7 +122,7 @@ export interface ClassComponent { * implementation code. */ export type ConcreteComponent< - Props = any, + Props = {}, RawBindings = any, D = any, C extends ComputedOptions = ComputedOptions, @@ -136,14 +136,14 @@ export type ConcreteComponent< * The constructor type is an artificial type returned by defineComponent(). */ export type Component< - Props = any, + Props = {}, RawBindings = any, D = any, C extends ComputedOptions = ComputedOptions, M extends MethodOptions = MethodOptions > = | ConcreteComponent - | ComponentPublicInstanceConstructor // TODO infer types + | ComponentPublicInstanceConstructor // This shouldn't work :thinking: export { ComponentOptions } diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index 0b94cf180a3..9cc614a30ba 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -232,7 +232,7 @@ export type ComponentOptionsWithObjectProps< > export type ComponentOptions< - Props = any, + Props = {}, RawBindings = any, D = any, C extends ComputedOptions = ComputedOptions, diff --git a/packages/runtime-core/src/h.ts b/packages/runtime-core/src/h.ts index 86e0d86cc3a..38e4a0bc3a9 100644 --- a/packages/runtime-core/src/h.ts +++ b/packages/runtime-core/src/h.ts @@ -112,13 +112,17 @@ export function h( // catch-all for generic component types export function h(type: Component, children?: RawChildren): VNode +// component without props +export function h( + type: Component, + props: null, + children?: RawChildren | RawSlots +): VNode + // exclude `defineComponent` constructors -export function h< - T extends ComponentOptions

| FunctionalComponent, - P ->( - type: T, - props: (RawProps & P) | ({} extends P ? null : never), +export function h

( + type: ComponentOptions

, + props?: (RawProps & P) | ({} extends P ? null : never), children?: RawChildren | RawSlots ): VNode @@ -129,11 +133,12 @@ export function h

( props?: (RawProps & P) | ({} extends P ? null : never), children?: RawChildren | RawSlots ): VNode + // fake constructor type returned by `defineComponent` export function h(type: DefineComponent, children?: RawChildren): VNode export function h

( type: DefineComponent

, - props: (RawProps & P) | ({} extends P ? null : never), + props?: (RawProps & P) | ({} extends P ? null : never), children?: RawChildren | RawSlots ): VNode diff --git a/test-dts/component.test-d.ts b/test-dts/component.test-d.ts index 6addd922175..ee86e122479 100644 --- a/test-dts/component.test-d.ts +++ b/test-dts/component.test-d.ts @@ -8,7 +8,8 @@ import { expectError, expectType, ShallowUnwrapRef, - FunctionalComponent + FunctionalComponent, + ComponentPublicInstance } from './index' declare function extractComponentOptions( @@ -398,6 +399,14 @@ describe('functional', () => { }) }) +declare type VueClass = { + new (): ComponentPublicInstance +} + describe('class', () => { - // TODO + const MyComponent: VueClass<{ foo: number }> = {} as any + + const { props } = extractComponentOptions(MyComponent) + + expectType(props.foo) }) From 114e067b5d0095a703f2293dce38c83f7839d17b Mon Sep 17 00:00:00 2001 From: pikax Date: Thu, 20 Aug 2020 11:44:25 +0100 Subject: [PATCH 19/24] chore: ... --- packages/runtime-core/src/component.ts | 2 +- packages/runtime-core/src/componentOptions.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 4c97a34ac7e..65cf105984a 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -136,7 +136,7 @@ export type ConcreteComponent< * The constructor type is an artificial type returned by defineComponent(). */ export type Component< - Props = {}, + Props = any, RawBindings = any, D = any, C extends ComputedOptions = ComputedOptions, diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index 9cc614a30ba..fa4428dafe5 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -235,8 +235,8 @@ export type ComponentOptions< Props = {}, RawBindings = any, D = any, - C extends ComputedOptions = ComputedOptions, - M extends MethodOptions = MethodOptions + C extends ComputedOptions = any, + M extends MethodOptions = any > = ComponentOptionsBase export type ComponentOptionsMixin = ComponentOptionsBase< From 832bec696b9ca50ebe959d143e3e5ccad43e98d8 Mon Sep 17 00:00:00 2001 From: pikax Date: Thu, 20 Aug 2020 11:57:21 +0100 Subject: [PATCH 20/24] chore: fixed? --- packages/runtime-core/src/componentOptions.ts | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index fa4428dafe5..5517e31299e 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -237,7 +237,33 @@ export type ComponentOptions< D = any, C extends ComputedOptions = any, M extends MethodOptions = any -> = ComponentOptionsBase +> = + | ComponentOptionsWithoutProps + | ComponentOptionsWithObjectProps< + any, + RawBindings, + D, + C, + M, + any, + any, + any, + any, + Props + > + | ComponentOptionsWithArrayProps< + any, + RawBindings, + D, + C, + M, + any, + any, + any, + any, + Props + > + | ComponentOptionsBase export type ComponentOptionsMixin = ComponentOptionsBase< any, From dac2393c60a143224eec513fbd7c489ef92261c9 Mon Sep 17 00:00:00 2001 From: pikax Date: Thu, 20 Aug 2020 11:59:44 +0100 Subject: [PATCH 21/24] chore: improve? --- packages/runtime-core/src/componentOptions.ts | 69 ++++++++++++------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index 5517e31299e..cdb43cb699e 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -236,34 +236,51 @@ export type ComponentOptions< RawBindings = any, D = any, C extends ComputedOptions = any, - M extends MethodOptions = any + M extends MethodOptions = any, + Mixin extends ComponentOptionsMixin = any, + Extends extends ComponentOptionsMixin = any, + E extends EmitsOptions = any > = - | ComponentOptionsWithoutProps - | ComponentOptionsWithObjectProps< - any, - RawBindings, - D, - C, - M, - any, - any, - any, - any, - Props - > - | ComponentOptionsWithArrayProps< - any, - RawBindings, - D, - C, - M, - any, - any, - any, - any, - Props + // | ComponentOptionsWithoutProps + // | ComponentOptionsWithObjectProps< + // any, + // RawBindings, + // D, + // C, + // M, + // any, + // any, + // any, + // any, + // Props + // > + // | ComponentOptionsWithArrayProps< + // any, + // RawBindings, + // D, + // C, + // M, + // any, + // any, + // any, + // any, + // Props + // > + // | + ComponentOptionsBase & + ThisType< + CreateComponentPublicInstance< + {}, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + Readonly + > > - | ComponentOptionsBase export type ComponentOptionsMixin = ComponentOptionsBase< any, From ba11f2a543f396c448eed2cb054baaecaf44d387 Mon Sep 17 00:00:00 2001 From: pikax Date: Thu, 20 Aug 2020 12:08:15 +0100 Subject: [PATCH 22/24] chore: remove commented code --- packages/runtime-core/src/componentOptions.ts | 53 +++++-------------- 1 file changed, 13 insertions(+), 40 deletions(-) diff --git a/packages/runtime-core/src/componentOptions.ts b/packages/runtime-core/src/componentOptions.ts index cdb43cb699e..e6a0dcf47ac 100644 --- a/packages/runtime-core/src/componentOptions.ts +++ b/packages/runtime-core/src/componentOptions.ts @@ -240,47 +240,20 @@ export type ComponentOptions< Mixin extends ComponentOptionsMixin = any, Extends extends ComponentOptionsMixin = any, E extends EmitsOptions = any -> = - // | ComponentOptionsWithoutProps - // | ComponentOptionsWithObjectProps< - // any, - // RawBindings, - // D, - // C, - // M, - // any, - // any, - // any, - // any, - // Props - // > - // | ComponentOptionsWithArrayProps< - // any, - // RawBindings, - // D, - // C, - // M, - // any, - // any, - // any, - // any, - // Props - // > - // | - ComponentOptionsBase & - ThisType< - CreateComponentPublicInstance< - {}, - RawBindings, - D, - C, - M, - Mixin, - Extends, - E, - Readonly - > +> = ComponentOptionsBase & + ThisType< + CreateComponentPublicInstance< + {}, + RawBindings, + D, + C, + M, + Mixin, + Extends, + E, + Readonly > + > export type ComponentOptionsMixin = ComponentOptionsBase< any, From 99b4bf0657a74de6ec9efec595f5b3403533acea Mon Sep 17 00:00:00 2001 From: pikax Date: Fri, 21 Aug 2020 08:49:03 +0100 Subject: [PATCH 23/24] chore: remove comment --- packages/runtime-core/src/component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 65cf105984a..6960c89bf4d 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -143,7 +143,7 @@ export type Component< M extends MethodOptions = MethodOptions > = | ConcreteComponent - | ComponentPublicInstanceConstructor // This shouldn't work :thinking: + | ComponentPublicInstanceConstructor export { ComponentOptions } From 03dfaa5d1872929473485085f9adb99a2395e52b Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 15 Sep 2020 10:47:50 -0400 Subject: [PATCH 24/24] refactor: improve typing --- packages/reactivity/src/baseHandlers.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/reactivity/src/baseHandlers.ts b/packages/reactivity/src/baseHandlers.ts index b6f56f162cb..2b7b29b03a8 100644 --- a/packages/reactivity/src/baseHandlers.ts +++ b/packages/reactivity/src/baseHandlers.ts @@ -32,17 +32,17 @@ const readonlyGet = /*#__PURE__*/ createGetter(true) const shallowReadonlyGet = /*#__PURE__*/ createGetter(true, true) const arrayInstrumentations: Record = {} -;['includes', 'indexOf', 'lastIndexOf'].forEach(key => { - arrayInstrumentations[key] = function(...args: any[]): any { - const arr = toRaw(this) as any - for (let i = 0, l = (this as any).length; i < l; i++) { +;(['includes', 'indexOf', 'lastIndexOf'] as const).forEach(key => { + arrayInstrumentations[key] = function(this: unknown[], ...args: unknown[]) { + const arr = toRaw(this) + for (let i = 0, l = this.length; i < l; i++) { track(arr, TrackOpTypes.GET, i + '') } // we run the method using the original args first (which may be reactive) - const res = arr[key](...args) + const res = (arr[key] as any)(...args) if (res === -1 || res === false) { // if that didn't work, run it again using raw values. - return arr[key](...args.map(toRaw)) + return (arr[key] as any)(...args.map(toRaw)) } else { return res }