Skip to content

fix: make generics with runtime props in defineComponent work (fix #11374) #13119

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 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
99 changes: 88 additions & 11 deletions packages-private/dts-test/defineComponent.test-d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1373,7 +1373,7 @@ describe('function syntax w/ emits', () => {
describe('function syntax w/ runtime props', () => {
// with runtime props, the runtime props must match
// manual type declaration
defineComponent(
const Comp1 = defineComponent(
(_props: { msg: string }) => {
return () => {}
},
Expand All @@ -1382,7 +1382,34 @@ describe('function syntax w/ runtime props', () => {
},
)

// @ts-expect-error bar isn't specified in props definition
defineComponent(
(_props: { msg: string }) => {
return () => {}
},
{
props: ['msg', 'bar'],
},
)

defineComponent(
(_props: { msg: string; bar: string }) => {
return () => {}
},
{
props: ['msg'],
},
)

expectType<JSX.Element>(<Comp1 msg="1" />)
// @ts-expect-error msg type is incorrect
expectType<JSX.Element>(<Comp1 msg={1} />)
// @ts-expect-error msg is missing
expectType<JSX.Element>(<Comp1 />)
// @ts-expect-error bar doesn't exist
expectType<JSX.Element>(<Comp1 msg="1" bar="2" />)

const Comp2 = defineComponent(
<T extends string>(_props: { msg: T }) => {
return () => {}
},
Expand All @@ -1391,7 +1418,36 @@ describe('function syntax w/ runtime props', () => {
},
)

// @ts-expect-error bar isn't specified in props definition
defineComponent(
<T extends string>(_props: { msg: T }) => {
return () => {}
},
{
props: ['msg', 'bar'],
},
)

defineComponent(
<T extends string>(_props: { msg: T; bar: T }) => {
return () => {}
},
{
props: ['msg'],
},
)

expectType<JSX.Element>(<Comp2 msg="1" />)
expectType<JSX.Element>(<Comp2<string> msg="1" />)
// @ts-expect-error msg type is incorrect
expectType<JSX.Element>(<Comp2 msg={1} />)
// @ts-expect-error msg is missing
expectType<JSX.Element>(<Comp2 />)
// @ts-expect-error bar doesn't exist
expectType<JSX.Element>(<Comp2 msg="1" bar="2" />)

// Note: generics aren't supported with object runtime props
const Comp3 = defineComponent(
<T extends string>(_props: { msg: T }) => {
return () => {}
},
Expand All @@ -1402,37 +1458,58 @@ describe('function syntax w/ runtime props', () => {
},
)

// @ts-expect-error string prop names don't match
defineComponent(
(_props: { msg: string }) => {
// @ts-expect-error bar isn't specified in props definition
<T extends string>(_props: { msg: T }) => {
return () => {}
},
{
props: ['bar'],
props: {
bar: String,
},
},
)

defineComponent(
(_props: { msg: string }) => {
// @ts-expect-error generics aren't supported with object runtime props
<T extends string>(_props: { msg: T; bar: T }) => {
return () => {}
},
{
props: {
// @ts-expect-error prop type mismatch
msg: Number,
msg: String,
},
},
)

// @ts-expect-error prop keys don't match
expectType<JSX.Element>(<Comp3 msg="1" />)
// @ts-expect-error generics aren't supported with object runtime props
expectType<JSX.Element>(<Comp3<string> msg="1" />)
// @ts-expect-error msg type is incorrect
expectType<JSX.Element>(<Comp3 msg={1} />)
// @ts-expect-error msg is missing
expectType<JSX.Element>(<Comp3 />)
// @ts-expect-error bar doesn't exist
expectType<JSX.Element>(<Comp3 msg="1" bar="2" />)

// @ts-expect-error string prop names don't match
defineComponent(
(_props: { msg: string }, ctx) => {
(_props: { msg: string }) => {
return () => {}
},
{
props: ['bar'],
},
)

defineComponent(
(_props: { msg: string }) => {
return () => {}
},
{
props: {
msg: String,
bar: String,
// @ts-expect-error prop type mismatch
msg: Number,
},
},
)
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime-core/src/apiDefineComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export function defineComponent<
ctx: SetupContext<E, S>,
) => RenderFunction | Promise<RenderFunction>,
options?: Pick<ComponentOptions, 'name' | 'inheritAttrs'> & {
props?: (keyof Props)[]
props?: (keyof NoInfer<Props>)[]
emits?: E | EE[]
slots?: S
},
Expand Down