Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue TSX - How to tell Typescript that the HTML attributes are allowed in reusable components?

Suppose I have this input component:

import { defineComponent } from "@vue/runtime-core"

export default defineComponent({
    inheritAttrs: false,
    setup(props, { attrs }) {
        return () => (
            <div>
                <input type="text" {...attrs} />
            </div>
        )
    }
})

Now, I use this component like so and provide type="password" attribute:

import { defineComponent } from "@vue/runtime-core"
import Input from "./components/input"

export default defineComponent({
    setup(props, { attrs }) {
        return () => <Input type="password"></Input>
    }
})

But Typescript complains:

Property 'type' does not exist on type 'IntrinsicAttribute'> & VNodeProps & AllowedComponentProps & ComponentCustomProps>'
like image 448
Damon Avatar asked Mar 18 '21 04:03

Damon


1 Answers

So I am not a Vue.JS expert (please tell me if it doesn't work and why), but after some research I found out that you have to type the props by adding a props object to defineComponent. That will tell TypeScript that you can pass specific props.

import { defineComponent } from "@vue/runtime-core"

export default defineComponent({
    inheritAttrs: false,
    props: {
        type: String // this is the typing (warning: you cannot use typescript types here)
    }
    setup(props, { attrs }) {
        return () => (
            <div>
                <input type={props.type ?? "text"} {...attrs} />
            </div>
        )
    }
})

You might ask what the ?? operator does. I like to call it the "defaulting operator" because it default the value before it with the value after it. In this case it means that if props.type is undefined or null it will replace it with "text".

like image 130
blaumeise20 Avatar answered Oct 19 '22 18:10

blaumeise20