Skip to content
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

Support passing generic to child components #8015

Closed
KawaiiZapic opened this issue Apr 3, 2023 · 6 comments · Fixed by vuejs/language-tools#4971
Closed

Support passing generic to child components #8015

KawaiiZapic opened this issue Apr 3, 2023 · 6 comments · Fixed by vuejs/language-tools#4971
Labels

Comments

@KawaiiZapic
Copy link

KawaiiZapic commented Apr 3, 2023

What problem does this feature solve?

We can pass type parameter in TypeScript via generics:

function <T extends string | number>doSth(value:T): T[] {
  if (value === "123") {
    return toArray(123);  // throw an error, number[] is not compatible with T[]
  }
 return toArray<T>(value)
}

But we cannot do so in Vue template.

<my-select v-model="selectedFruit">
  <my-option value="🍎" />
  <my-option value="🍌" />
  <my-option value="🐘" /> // should throw an error, 🐘 is not compatible with selectedFruit 
</my-select>

To make this possible, we need the ability to restrict what components can be in slot:

defineSlots({
   default: {
     accept: MyOption<T>
  }
})
<my-select v-model="selectedFruit">
  <my-option value="🍎" />
  <my-option value="🍌" />
  <my-option value="🐘" /> // 🐘 is  not compatible with selectedFruit 
</my-select>

also, now we have ability to prevent developer from putting unexpected components in slots!

<my-select v-model="selectedFruit as any">
   <my-radio v-model="radioValue" /> // throw an error, my-radio should not be here
</my-select>

Sometimes TypeScript cannot infer acutal type we want:

<my-button-group :buttons="['🍚', '🍗']" @click="handleUpdate" />
type Foods = '🍚' | '🍗';
const handleClick= (food: Foods) => {
   console.log(food);
}

buttons will infer as string[], and @click handle is (value: string) => void, but we need Foods[] and (value: Foods) => void
So we also need ability to specify what type we want:

<my-button-group[Foods] :buttons="['🍚', '🍗']" @click="handleUpdate" />

What does the proposed API look like?

For template:

<my-select[typeof selectedFruit] v-model="selectedFruit">
   <my-option value="🍎" />
   <my-option value="🍌" /> 
   <my-option value="🐘" /> // 🐘 is not compatible with selectedFruit 
</my-select>
<my-select v-generics="typeof selectedFruit" v-model="selectedFruit">
   <my-option value="🍎" />
   <my-option value="🍌" /> 
   <my-option value="🐘" /> // 🐘 is not compatible with selectedFruit 
</my-select>

For slot type definition:

defineSlots({
   default: {
     accept: MyOption<T>
  }
})
@KawaiiZapic KawaiiZapic added the ✨ feature request New feature or request label Apr 3, 2023
@sxzz
Copy link
Member

sxzz commented Apr 3, 2023

This is an issue that requires consideration. In my opinion, using v-generic (in line with <script setup lang="ts" generic="T">) would be preferable. It's not feasible to add generics to the element tag as we need to maintain compatibility with native HTML code.

For slots, see #7982 (comment)


/cc @johnsoncodehk

@longshihui
Copy link

I have same requirements

@an501920078
Copy link

Much needed feature

@Allihol
Copy link

Allihol commented May 5, 2023

附议。很需要这个功能,团队不方便用jsx
Much needed feature

@robinbeatty
Copy link

+1 for this

@MarkusJLechner
Copy link

I just stumbled upon this issue, but unfortunately, there's no solution yet. This issue has been open for over a year; it's quite a specific problem and might not be resolved anytime soon..

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

Successfully merging a pull request may close this issue.

7 participants