Skip to content

Support passing generic to child components  #8015

Description

@KawaiiZapic

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>
  }
})

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions