-
-
Notifications
You must be signed in to change notification settings - Fork 390
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
feat: Support RFC 436 (Experimental) #1964
Conversation
Ping vuejs/rfcs#436 |
Full of excitement I tried it right away in my multiselect component. In my multiselect component I did this: Template passed as an item template: When using it, I made sure to pass 'class ExtendedItem extends Item' arrays to both params. Are there any extra steps required? NOTE: I made sure to first update Volar extension and vue-tsc to 1.0.3 |
@StepanMynarik I think the current design is not enough to support generic typed slots, we may need a new const { items, selectedItem, } = defineProps<{ items: T[]; selectedItem: T[]; }>();
defineSlots<{ default(args: { item: T }): VNode[] }>(); It's better to present your use case in an RFC so peoples can discuss with it. |
@johnsoncodehk Oh, I must have got it wrong. What is the current intended use case then? I will make sure to post my use case to the RFC, good point. |
@StepanMynarik I'm checking if this might working without add new API, will let you know later. |
@StepanMynarik please track #1987 |
Defining props with the <script setup lang="ts" generic="T extends string | number">
const props = defineProps<{ msg: T }>();
</script> I found that you can also define props via an interface but you need to export the interface for it to work. <script setup lang="ts" generic="T extends string | number">
export interface Props<T> {
msg: T;
}
const props = defineProps<Props<T>>();
</script> If you don't |
@colinj you should move interface to <script lang="ts">
interface Props<T> {
msg: T;
}
</script>
<script setup lang="ts" generic="T extends string | number">
const props = defineProps<Props<T>>();
</script> You can use |
I thought I'd try using <script lang="ts">
interface Props<T> {
msg?: T;
}
</script>
<script setup lang="ts" generic="T extends string | number">
const props = withDefaults(defineProps<Props<T>>(), {
msg: "Fred", // TS Error
// Type 'string' is not assignable to type 'InferDefault<Readonly<Props<T>>, NotUndefined<T>>'.ts(2322)
}); |
This is <script lang="ts">
interface Props<T> {
msg?: T;
}
</script>
<script setup lang="ts" generic="T extends string | number">
const props = withDefaults(defineProps<Props<T>>() as Props<string | number>, {
msg: "Fred",
});
</script> |
Yes, I started to look inside |
I am also getting eslint (no-undef) errors for module.exports = {
...
rules: { ... },
globals: {
T: "readonly", // naming convention used to define the type on generic Vue components
},
}; Obviously, this means I would need to use |
Enabling
|
@johnsoncodehk Can you also see this issue #1405 (comment) ? |
Type checking works amazing and passes but I do get this message in VSCode anytime a generic is used inside defineProps:
<script lang="ts" setup generic="TC extends readonly string[] | string[]">
defineProps<{
options: TC;
}>()
</script> |
I noticed this working amazingly during dev builds - but prod builds are broken as it cannot seem to be able to resolve the file (te name seems to include the generic part) - but that may also be caused because I am using |
but vue has issue with this ts new feature |
Same here with |
For those using vue 3, you need to paste the following in tsconfig.app.json:
|
I get the same error as well. Does anyone know how to resolve it? |
Is it possible to use this with Vite? |
I tried this today, and the improvement in DX is genuinely amazing. I only have two issues with this, which if they can be improved, brilliant:
//DataDisplay.vue
<script setup lang="ts" generic="T extends any">
const props = defineProps<{
data: T[] | undefined;
}>();
const realData: Ref<T> = computed(() => (props.data == null ? undefined : props.data[0]) as Exclude<T, undefined>);
</script>
//App.vue
<template>
<!-- Only want to pass in a single `T`, but forced to wrap it in an array. -->
<DataDisplay :data="[5]"/>
</template>
This is fine for simple components, but the bandages are a bit of an annoyance. I hope this progress rapidly because it improves Vue for the way-better. |
This is working for me with Vite. I am running into the cyclic type error as others have mentioned though. |
This is freaking amazing. The one thing that kept React better suited for large project was this. Please, oh please make this official fast, please...I typed our ui lib with this and it boosted DX 10 fold |
A nice example if you want to type the <script setup lang="ts" generic="VueGen extends AppSelectOption<string | number>">
export interface AppSelectOption<T extends string | number> {
value: T,
text: string;
disabled?: boolean;
}
export interface Props<T extends AppSelectOption<string | number>> {
text: string;
modelValue: T['value'] | undefined;
options: readonly T[];
disabled?: boolean;
}
defineProps<Props<VueGen>>();
const emits = defineEmits<{
(e: 'update:modelValue', modelValue: VueGen['value']): void;
}>();
function onChange (e: Event): void {
const target = e.target as HTMLSelectElement;
emits('update:modelValue', target.value);
}
</script>
<template>
<label>
{{ text }}
<select
:value="modelValue"
:disabled="disabled"
@change="onChange"
>
<option
v-for="option in options"
:key="option.value"
:value="option.value"
:disabled="option.disabled"
>
{{ option.text }}
</option>
</select>
</label>
</template> This also allows to set the value as undefined in case you don want any pre-selected option. But I'm also facing the |
To everyone running into the |
@yyx990803 Here's a minimum repo with the error reproduction with the Select example I posted. Using TypeScript 4.9.5 locally from global. |
I'm unable to provide a repro ATM. I'll at-least confirm my versions: Typescript 4.9.5, Volar v1.2.0, Vue 3.2.45, Vue-Tsc 1.2.0. |
|
Thanks! Yeah, this really solved the issue! 💚 |
I just upgraded typescript to |
RFC: vuejs/rfcs#436
Usage
Please note that
extends any
is required, otherwise JSX syntax will be broken.