Subscribe on changes!

[QUESTION] How to allow HTML attributes as props while using Typescript JSX?

avatar
Mar 20th 2021

Version

3.0.7

Reproduction link

https://github.com/sanjade/vue3-bug

Steps to reproduce

First of all, I know this kind of issue shouldn't be asked here but I just wanted to tell you that I did try asking the question in StackOverflow. However it has no response and it's been 2 days.

- git clone https://github.com/sanjade/vue3-bug
- cd vue3-bug && yarn
- Goto `App.tsx` and you will see the error in `type` attribute

What is expected?

Suppose I have this input component:

// components/input.tsx

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:

// App.tsx

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

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

I expect Typescript not to throw any error.

What is actually happening?

But Typescript complains in App.tsx:

(JSX attribute) type: string
Type '{ type: string; }' is not assignable to type 'IntrinsicAttributes & Partial<{}> & Omit<Readonly<{} & {}> & VNodeProps & AllowedComponentProps & ComponentCustomProps, never>'.
  Property 'type' does not exist on type 'IntrinsicAttributes & Partial<{}> & Omit<Readonly<{} & {}> & VNodeProps & AllowedComponentProps & ComponentCustomProps, never>'.ts(2322)

How do you specify that InputHTMLAttributes are also allowed as props in the input.tsx component?

avatar
Mar 21st 2021

You can use functional components for that purpose

import { FunctionalComponent } from 'vue'

const MyInput: FunctionalComponent<InputHTMLAttributes & { foo?: string}> = (props) => {
  return <input {...props}/>
}

const el = <MyInput foo="str" autofocus type="xxx"  />

For defineComponent, it needs to be improved, this is related RFC https://github.com/vuejs/rfcs/pull/281. BTW, you can ask questions on the forum, the Discord server or StackOverflow.

avatar
Apr 10th 2021

image

when i define functional component props it will display type errors

TS2322: Type '{ p1: StringConstructor; p2: NumberConstructor; onP1: { type: FunctionConstructor; }; }' is not assignable to type 'ComponentPropsOptions<FuncCompProps> | undefined'.   Types of property 'onP1' are incompatible.     Type '{ type: FunctionConstructor; }' is not assignable to type 'Prop<() => void, () => void> | null | undefined'.       Types of property 'type' are incompatible.         Type 'FunctionConstructor' is not assignable to type 'true | PropType<() => void> | null | undefined'.           Type 'FunctionConstructor' is not assignable to type '() => () => void'.             Type 'Function' is not assignable to type '() => void'.               Type 'Function' provides no match for the signature '(): void'.
import { defineComponent, FunctionalComponent } from 'vue'

interface FuncCompProps {
  p1: string
  p2: number
  onP1(): void
}
const FuncComp: FunctionalComponent<FuncCompProps> = (props, ctx) => {
  return <div>{props.p1}</div>
}
FuncComp.inheritAttrs = false
FuncComp.displayName = 'Func'
FuncComp.props = {
  p1: String,
  p2: Number,
  onP1: {
    type: Function,
  }
}

and i want to define stateful component like a union one style. the below code is

interface StateFulCompProps {
  s1: string
  s2: number
  onS1(): void
}

const StateFulComp = defineComponent<StateFulCompProps>((props, ctx) => {
  return () => <div>{props.s1}</div>
})
StateFulComp.inheritAttrs = false
StateFulComp.displayName = 'StateFulComp'
StateFulComp.props = {
  s1: String,
  s2: Number,
  onS1: Function,
}

in webstorm ide has some mistakes

  • the functinal props type will display right. but stateful props type display error image image

  • the stateful component props will change optional (string | undefined)

how can i explicit declare the component props type in stateful coponent ?

@HcySunYang thanks

avatar
Jan 4th 2023