Skip to content

types(defineComponent): Stricter Component Type + helpers #9556

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 83 commits into
base: minor
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
b256412
WIP: component helper types
pikax Nov 6, 2023
e1ef6a8
fix one issue
pikax Nov 6, 2023
fbd083b
working kinda
pikax Nov 6, 2023
8934665
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 6, 2023
e7c0383
add Extract component Options
pikax Nov 6, 2023
5f86b19
added types
pikax Nov 6, 2023
22c304c
more tests
pikax Nov 8, 2023
c2c0958
working few things
pikax Nov 8, 2023
3fbfe6f
cleanup
pikax Nov 8, 2023
99e48a7
removed unused
pikax Nov 8, 2023
1ce7234
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 8, 2023
d88f7af
remove stuff temp
pikax Nov 8, 2023
3b653cd
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 8, 2023
9b23cdf
small improvements
pikax Nov 9, 2023
de726ac
Merge branch 'main' into pikax/component_helper_types
pikax Nov 10, 2023
8b1faf7
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 10, 2023
ae7b51b
export LooseRequired
pikax Nov 10, 2023
9e67b17
WIP DefineComponentOptions type
pikax Nov 13, 2023
f6f82fa
WIP building
pikax Nov 14, 2023
0506beb
test passing
pikax Nov 14, 2023
3e29651
fix other issues
pikax Nov 14, 2023
48a0b08
remove render function type
pikax Nov 14, 2023
6d1db29
async component changes
pikax Nov 14, 2023
f47bc76
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 14, 2023
bbad2f8
support more overloads on defineComponet and also support VNode on h
pikax Nov 14, 2023
1d40c76
add vnode support
pikax Nov 15, 2023
998607e
few more changes
pikax Nov 15, 2023
4254fac
Merge branch 'main' into pikax/component_helper_types
pikax Nov 15, 2023
633b852
more work
pikax Nov 16, 2023
96f244a
more improvements
pikax Nov 16, 2023
aab3189
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 16, 2023
8a61db8
some improvements
pikax Nov 17, 2023
3d8a5c0
more improvements and add some comments
pikax Nov 18, 2023
ca626bf
more improvments
pikax Nov 18, 2023
b2c4a38
Merge branch 'main' into pikax/component_helper_types
pikax Nov 18, 2023
9853470
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 18, 2023
0d0bf05
fix componentSlots
pikax Nov 20, 2023
9ae88d3
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 20, 2023
f62ae36
support volar syntax for slots
pikax Nov 20, 2023
413d556
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 20, 2023
836a930
introducing DeclareComponent type
pikax Nov 20, 2023
8336ba5
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 20, 2023
77ca7b1
chore: renaming & lint
pikax Nov 21, 2023
bba1cde
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 21, 2023
ab9823d
fix test type
pikax Nov 21, 2023
c98c360
chore: some changes
pikax Nov 22, 2023
86826aa
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 22, 2023
92057db
some imrpovements
pikax Nov 22, 2023
b015918
chore: some improvements
pikax Nov 22, 2023
6819d05
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 22, 2023
f3119d4
types: change DefineComponent defaults to be more lenient
pikax Nov 23, 2023
53f2af0
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 23, 2023
018223d
chore: improve ComponentData
pikax Nov 23, 2023
5e9d759
Custom props
pikax Nov 24, 2023
73f52d3
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 24, 2023
bf6286d
kinda working
pikax Nov 25, 2023
aa91257
remov efunction
pikax Nov 25, 2023
bb4cf93
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 25, 2023
d483491
chore: fix tests
pikax Nov 28, 2023
b1094a6
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 28, 2023
b4b62d0
chore: render function
pikax Nov 28, 2023
46cc5cb
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 28, 2023
cc2ed2a
chore: remove comments
pikax Nov 28, 2023
e777107
Merge branch 'minor' into pikax/component_helper_types
pikax Dec 29, 2023
eaa2ded
type fixing
pikax Dec 29, 2023
e3d217b
fix tests
pikax Dec 29, 2023
e063b78
fix tests
pikax Dec 29, 2023
e8e937b
chore: review
pikax Dec 29, 2023
fb2e70b
chore: improve defineAsyncComponent types
pikax Dec 30, 2023
5c0c261
chore: improve tests for async component
pikax Dec 30, 2023
37ca2cb
chore: some improvements + tests
pikax Dec 31, 2023
e9c7dfc
added DeclareEmits and removed shortEmits type
pikax Jan 13, 2024
b56836f
EmitsOptions to support events
pikax Jan 13, 2024
f3b9c28
improve type resolution when using ComponentEmits on DeclareComponent
pikax Jan 13, 2024
3b307e3
chore: improve ObjectToProps, to keep the original type
pikax Jan 13, 2024
b8b99a8
chore: Added DynamicComponent type helper
pikax Jan 13, 2024
7866070
chore: fix typo
pikax Jan 13, 2024
c6c8caf
chore: add a few tests for DynamicComponent
pikax Jan 13, 2024
42301b3
chore: improve types
pikax Jan 16, 2024
3ff6732
chore: clean up types, prevent object properties being overridden
pikax Jan 16, 2024
39b9ade
chore: fix usage of ComponentProps on DeclareComponent
pikax Jan 17, 2024
5890e8c
chore: fix type inferrence on props
pikax Jan 17, 2024
bdc1d73
chore: improvements on resolving props
pikax Jan 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
add Extract component Options
  • Loading branch information
pikax committed Nov 6, 2023
commit e7c0383e28a649c8782e8c66800196f70de0811f
168 changes: 146 additions & 22 deletions packages/dts-test/componentTypeHelpers.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,154 @@
// import { expectType, describe } from './utils'
import { expectType, describe } from './utils'

// import {
// ExtractComponentOptions,
// ExtractComponentSlots,
// ExtractComponentEmits,
// defineComponent
// } from 'vue'
import {
ExtractComponentOptions,
ExtractComponentSlots,
ExtractComponentEmits,
defineComponent,
defineAsyncComponent
} from 'vue'

// describe('Extract Component Options', () => {
// describe('define Component', () => {
// // const comp = {
// // props: ['bar']
// // } as const
declare function extractComponentOptions<T>(comp: T): ExtractComponentOptions<T>

// const Comp = defineComponent({
// props: ['bar']
// })
declare function extractComponentSlots<T>(comp: T): ExtractComponentSlots<T>
describe('Extract Component Options', () => {
describe('defineComponent', () => {
const propsOptions = {
props: {
a: String,
b: Boolean,

// const a = {} as unknown as ExtractComponentOptions<typeof Comp>
bb: {
type: Boolean,
required: true
}
},
slots: {
default(arg: { msg: string }) {}
},
foo: 'bar',
data() {
return {
test: 1
}
}
}
// Component with props
const CompProps = defineComponent(propsOptions)
expectType<ExtractComponentOptions<typeof CompProps>>(propsOptions)
// @ts-expect-error checking if is not any
expectType<ExtractComponentOptions<typeof CompProps>>({ bar: 'foo' })

// a.props
// component array props
const arrayOptions = {
props: ['a', 'b', 'c'],
slots: {
default(arg: { msg: string }) {}
},
foo: 'bar',
data() {
return {
test: 1
}
}
}
const CompPropsArray = defineComponent(arrayOptions)
expectType<ExtractComponentOptions<typeof CompPropsArray>>(arrayOptions)
// @ts-expect-error checking if is not any
expectType<ExtractComponentOptions<typeof CompPropsArray>>({ bar: 'foo' })

// // expectType<ExtractComponentOptions<typeof Comp>>(comp)
// })
// component no props
const noPropsOptions = {
slots: {
default(arg: { msg: string }) {}
},
foo: 'bar',
data() {
return {
test: 1
}
}
}
const CompNoProps = defineComponent(noPropsOptions)
expectType<ExtractComponentOptions<typeof CompNoProps>>(noPropsOptions)
// @ts-expect-error checking if is not any
expectType<ExtractComponentOptions<typeof CompNoProps>>({ bar: 'foo' })
})

// describe('async component', () => {})
describe('async component', () => {
const Component = defineAsyncComponent({
loader: () =>
Promise.resolve(
defineComponent({
foo: 'bar'
})
)
})

// describe('options object', () => {})
// })
// NOTE not sure if this is the intention since Component.foo is undefined
expectType<ExtractComponentOptions<typeof Component>>({
foo: 'bar'
})
})

describe('options object', () => {
const propsOptions = {
props: {
a: String,
b: Boolean,

bb: {
type: Boolean,
required: true
}
},
slots: {
default(arg: { msg: string }) {}
},
foo: 'bar',
data() {
return {
test: 1
}
}
}

// Component with props
expectType<ExtractComponentOptions<typeof propsOptions>>(propsOptions)
// @ts-expect-error checking if is not any
expectType<ExtractComponentOptions<typeof propsOptions>>({ bar: 'foo' })

// component array props
const arrayOptions = {
props: ['a', 'b', 'c'],
slots: {
default(arg: { msg: string }) {}
},
foo: 'bar',
data() {
return {
test: 1
}
}
}
expectType<ExtractComponentOptions<typeof arrayOptions>>(arrayOptions)
// @ts-expect-error checking if is not any
expectType<ExtractComponentOptions<typeof arrayOptions>>({ bar: 'foo' })

// component no props
const noPropsOptions = {
slots: {
default(arg: { msg: string }) {}
},
foo: 'bar',
data() {
return {
test: 1
}
}
}
expectType<ExtractComponentOptions<typeof noPropsOptions>>(noPropsOptions)
// @ts-expect-error checking if is not any
expectType<ExtractComponentOptions<typeof noPropsOptions>>({ bar: 'foo' })
})
})
4 changes: 2 additions & 2 deletions packages/dts-test/defineComponent.test-d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1358,12 +1358,12 @@ describe('function syntax w/ runtime props', () => {
}
)

// @ts-expect-error string prop names don't match
defineComponent(
(_props: { msg: string }) => {
return () => {}
},
{
// @ts-expect-error string prop names don't match
props: ['bar']
}
)
Expand All @@ -1380,14 +1380,14 @@ describe('function syntax w/ runtime props', () => {
}
)

// @ts-expect-error prop keys don't match
defineComponent(
(_props: { msg: string }, ctx) => {
return () => {}
},
{
props: {
msg: String,
// @ts-expect-error prop keys don't match
bar: String
}
}
Expand Down
127 changes: 26 additions & 101 deletions packages/runtime-core/src/apiDefineComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ type ResolveProps<PropsOrPropOptions, E extends EmitsOptions> = Readonly<
> &
({} extends E ? {} : EmitsToProps<E>)

export declare const RawOptionsSymbol: unique symbol

export type DefineComponent<
PropsOrPropOptions = {},
RawBindings = {},
Expand Down Expand Up @@ -93,34 +95,16 @@ export type DefineComponent<
S
>,
'props'
> & { props: PropsOrPropOptions } & Omit<Options, '__asyncLoader'> &
PP
> & { props: PropsOrPropOptions } & Omit<Options, 'props'> & {
[RawOptionsSymbol]: Options
} & PP

// defineComponent 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
export function defineComponent<
Props extends Record<string, any>,
E extends EmitsOptions = {},
EE extends string = string,
S extends SlotsType = {},
Options = {}
>(
setup: (
props: Props,
ctx: SetupContext<E, S>
) => RenderFunction | Promise<RenderFunction>,
options?: Options &
Pick<ComponentOptions, 'name' | 'inheritAttrs'> & {
props?: (keyof Props)[]
emits?: E | EE[]
slots?: S
}
): (props: Props & EmitsToProps<E>) => any

export function defineComponent<
Props extends Record<string, any>,
E extends EmitsOptions = {},
Expand All @@ -137,54 +121,11 @@ export function defineComponent<
slots?: S
}
): (props: Props & EmitsToProps<E>) => any

// (uses user defined props interface)
export function defineComponent<
Props extends Record<string, any>,
E extends EmitsOptions = {},
EE extends string = string,
S extends SlotsType = {},
Options = {}
>(
setup: (
props: Props,
ctx: SetupContext<E, S>
) => RenderFunction | Promise<RenderFunction>,
options?: Options &
Pick<ComponentOptions, 'name' | 'inheritAttrs'> & {
props?: (keyof Props)[]
emits?: E | EE[]
slots?: S
}
): DefineComponent<
Props & EmitsToProps<E>,
{},
{},
{},
{},
{},
{},
E,
EE,
PublicProps,
ResolveProps<Props, E>,
ExtractDefaultPropTypes<Props>,
{},
string,
S,
{
name: string
} & Options
>

// extend({ name: options.name }, extraOptions, { setup: options }))()

export function defineComponent<
Props extends Record<string, any>,
E extends EmitsOptions = {},
EE extends string = string,
S extends SlotsType = {},
Options = {}
S extends SlotsType = {}
>(
setup: (
props: Props,
Expand All @@ -195,26 +136,7 @@ export function defineComponent<
emits?: E | EE[]
slots?: S
}
): DefineComponent<
Props & EmitsToProps<E>,
{},
{},
{},
{},
{},
{},
E,
EE,
PublicProps,
ResolveProps<Props, E>,
ExtractDefaultPropTypes<Props>,
{},
string,
S,
{
name: string
} & Options
>
): (props: Props & EmitsToProps<E>) => any

// overload 2: object format with no props
// (uses user defined props interface)
Expand Down Expand Up @@ -338,22 +260,24 @@ export function defineComponent<
EE extends string = string,
I extends ComponentInjectOptions = {},
II extends string = string,
S extends SlotsType = {}
S extends SlotsType = {},
Options = {}
>(
options: ComponentOptionsWithObjectProps<
PropsOptions,
RawBindings,
D,
C,
M,
Mixin,
Extends,
E,
EE,
I,
II,
S
>
options: Options &
ComponentOptionsWithObjectProps<
PropsOptions,
RawBindings,
D,
C,
M,
Mixin,
Extends,
E,
EE,
I,
II,
S
>
): DefineComponent<
PropsOptions,
RawBindings,
Expand All @@ -369,7 +293,8 @@ export function defineComponent<
ExtractDefaultPropTypes<PropsOptions>,
I,
II,
S
S,
Options
>

// implementation, close to no-op
Expand Down
Loading