vuejs/rfcs

Pure TypeScript props declaration for the Options API, like we have defineProps() for the Composition API?

rodrigocfd opened this issue · 4 comments

What problem does this feature solve?

According to the documentation, when using Options API with TypeScript, complex props can be validated by using the PropType utility:

import {defineComponent, PropType} from 'vue';

interface Person {
    name: string;
}

export default defineComponent({
    props: {
        person: {
            type: Object as PropType<Person>,
            required: true,
        },
    },
});

This props declaration is verbose because you are effectively typing each prop twice: first you say it's an Object, then you say the Object is in fact a Person.

If your prop has a type like type Foo = 'food' | number | null, things are even harder.

With the <script setup> way and the Composition API, we have the defineProps compiler macro, which is extremely clear and concise:

const props = defineProps<{
    person: Person;
}>();

I'm aware that the compiler macro is available only with <script setup>, which has an additional processing step where this macro is replaced with the actual prop declaration, which then feeds the "invisible" setup() method.

Now, in my not-so-fertile imagination, without knowing the underlying code, I imagine a better prop declaration for the Options API as being a generic parameter for the defineComponent call, something like:

export default defineComponent<{
    person: Person,
}>({

});

Is something like this technically possible? To keep backwards compatiblity, maybe another API like definePropComponent()?

It would be greatly useful to have a pure TypeScript declaration in Options API, like we have with the Composition API, since it would enforce the correct props declaration.

What does the proposed API look like?

A defineComponent() accepting a generic parameter to be taken as props. Emit declarations are actually pretty good already.

If backwards compatibility is an issue, a new API which would accept these generic parameters, something like definePropComponent().

I would love to have pure TypeScript props declaration in Options API, since I do really like the Options API more than the composition API. Also I tried to solve it with the setup block in the Options API, but I could not define the props there either.

cefn commented

I have been very confused why such a lot of separation from the core language (javascript or typescript) has taken place with SFC transpilation and script setup yet there's no signature like the one sketched below which eliminates the PropTypes betrayal and the defineProps transpiler macro hacks altogether.

In this trivial draft, the props type is defined through function Parameters, and the data type through function ReturnType. What's not to like?

<script type="ts">
interface MyProps{
  hello:string
}

export default defineSetup((props:{hello:string}) => {
  return {
    message: computed(() => props.hello === 'world' ? 'Party time, Excellent.' : 'Sad Keanu')
  }
})
</script>

If Vue has Functional Component envy this is how you get it.

Is there any progress?