Skip to content

Slots type is always inferred from the object property in the 2nd argument of defineComponent #12761

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
cernymatej opened this issue Jan 21, 2025 · 1 comment

Comments

@cernymatej
Copy link

Vue version

3.5.13

Link to minimal reproduction

https://play.vuejs.org/#eNrdVMFu00AQ/ZXBFwfJcYQKl+AGlaqHcqAV9a2u8NaeJC6bXWt37SaK/C98C1/G7K7juAUqxJFLYs++mX1v/Gb2wVldx22DwTxIdKGq2oBG09TAmVidZoHRWbDIRLWppTKwhxKXlcBzSe8ChYlgHcENl0anuxrp0eaeS2Fwa6CDpZIbCKl8+D4TVIXiaskKhGsla52kC9hnAqBlfA5pJrqnIFd3ANHNrOFmTiQ8HgjuMgoptIEzsbvYsk3NEU6f05zYArMZXMKjbHgJuK2xMGDWlYbiAAIjodFIUYR80JR7ET44Upf/+F4zxTZIbG31JKWqBkWpQRtVidViUluR80FrBIXZzp+0KNl3o/YlB8GLxWs47WUDKEpQAiYutp6EZdWGEdz6Q7BFY20T475DH+JJ3yJHIKZH6F57+J377yL725fvWd6GhAvv3HEmCHboq2VWvtzZ/0S7O3E+2TDRMM53FtBWJSlyBjBEdMAUTAhpgBUFau39keawQoGqKmCNisZB3reVbDTf+SxHdQ5X9w/WfUz/Ij9ErjFc0MAdv0Iy83NJQXoxSN+BGXSQ5NV0CpDaq0lA7uSgMjt3O5C3cyZ2eUTkZLNaP3d/5Rx/7w2vyclOn6XlxAwVbetzzyyH6dTfPJo2AtKisOdZAO3UiqR39xlIhN0eVvu+D5AsSp8d852uv9BiyZXD/U9c+U8MxhUIkcxGrQ0iWnxk/2W1ih+0FLQdnWOywG6LiqO6qk1F45EFtI98+Swgx8jHTy5mVIO9nShnjcW338Qf9NbGsuBaoUbVEvvhzDC1QuOPL24+07yMDjeybDihXzj8glryxnL0sI+NKIn2COfYXrq9Tv5O9YWdYH0QZYkexyULaIfbmf+T9CPdk/ht796Ouvi1RWVrUgNP4nfxm5Og+wmA2yiv

Steps to reproduce

Open the reproduction and have a look at the type of the val slot data property in both components.

interface Props<T> {
  val: T
}

interface Slots<T> {
  default: { val: T }
}

const AnyExample = defineComponent(
  // I would expect this component to use the `SlotsType` from the `SetupContext` parameter
  <T extends string>(props: Props<T>, ctx: SetupContext<{}, SlotsType<Slots<T>>>) => {
    return () => h('div', [
      ctx.slots.default?.({ val: props.val })
    ])
  },
  {
    props: ['val']
  }
)
<template>
  <!--  The `val` property here is `any`, though I would expect it to be the same type as the `val` prop => `'else'` -->
  <AnyExample val="else" v-slot="{ val }">
    {{ val }}
  </AnyExample>
</template>

What is expected?

When defining a component using defineComponent() with the new function signature, I would expect to be able to pass the generic types into the slots type.

defineComponent(
  <T extends string>(props: Props<T>, ctx: SetupContext<{}, SlotsType<Slots<T>>>) => {

What is actually happening?

The type of the generic properties in the slots is any, instead of the correct generic type.

System Info

Any additional comments?

No response

@danyadev
Copy link

danyadev commented Mar 30, 2025

I think it's related to the issue when generics stop working when the second argument of defineComponent is present

On the first screenshot everything is fine with the generic (except that props don't work)
On the second screenshot I've added a list of props, but the generic just disappeared

Image Image

Luckily, there is one option available: you can put additional properties using the old way:

const SelectLike = defineComponent(<T = string>(props: SelectLikeProps<T>) => {
  return () => <div>selected: {props.selected}</div>
})
// @ts-expect-error
SelectLike.props = ['options', 'selected', 'onChange']

There is a problem here though: properties like props don't exist in the types, so you'll need to put // @ts-expect-error on those lines, plus you'll lose autocompletion based on a user defined props definition

so /pull/7963 is technically done, but I don't see any way to use this feature :c

upd: I found an issue I'm talking about: /issues/11374

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants