[QUESTION] How to allow HTML attributes as props while using Typescript JSX?
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?
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.
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
the stateful component props will change optional (string | undefined)
how can i explicit declare the component props type in stateful coponent ?
@HcySunYang thanks
https://github.com/vuejs/rfcs/pull/477
cc @agileago @axelthat