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

1

6

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>'
Semester answered 18/3, 2021 at 4:7 Comment(0)
P
5

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".

Pennell answered 20/3, 2021 at 11:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.