Infer attrs for implementing HOCs #479
Replies: 10 comments 20 replies
-
How it will work in functional components? |
Beta Was this translation helpful? Give feedback.
-
I don't understand the motivation or the design.
In motivation you say:
As a Typescript user, I don't understand. I use TS and fall-through with no obvious issue, so I think it'd be worthwhile going into a little more details what the limitation is. Maybe even open an issue about it, there might be a more idiomatic way to fix the limitation you encounter without turning |
Beta Was this translation helpful? Give feedback.
-
Also, do not forget about the events. For example, a |
Beta Was this translation helpful? Give feedback.
-
UpdatedSince the 1. Option Componentconst Comp = defineComponent({
slots: Object as SlotsType<{
foo?: { data: string }
}>,
attrs: Object as AttrsType<{
bar?: string
}>,
setup(props, { slots, attrs }) {
console.log(attrs.bar)
slots.foo?.({ data: 'a' })
}
});
<Comp bar={"str"} />; 2. Functional Componentconst Comp = defineComponent(
(props: { foo: string }, ctx) => {
console.log(ctx.attrs.bar)
return () => (
<div>{props.foo}</div>
)
},
{
slots: Object as SlotsType<{
baz?: { data: string }
}>,
attrs: Object as AttrsType<{
bar?: number
}>
}
);
<Comp bar={1} foo={"str"} />; See vuejs/core#7444 |
Beta Was this translation helpful? Give feedback.
-
Specific scenes1. Wrapping a html elementimport { defineComponent, type ImgHTMLAttributes, type AttrsType } from 'vue';
const MyImg = defineComponent({
props: {
foo: String
},
attrs: Object as AttrsType<ImgHTMLAttributes>,
created() {
this.$attrs.class // any
this.$attrs.style // StyleValue | undefined
},
render() {
return <img {...this.$attrs} />
}
});
<MyImg class={'str'} style={'str'} src={'str'} />; 2. Wrapping a componentimport { defineComponent, type AttrsType, type ExtractPropsAndEvents } from 'vue';
const Child = defineComponent({
props: {
foo: String
},
emits: {
baz: (val: number) => true
},
render() {
return <div>{this.foo}</div>
}
});
const Comp = defineComponent({
props: {
bar: Number
},
attrs: Object as AttrsType<ExtractPropsAndEvents<typeof Child>>,
created() {
this.$attrs.class // unknown
this.$attrs.style // unknown
},
render() {
return <Child {...this.$attrs} />
}
});
<Comp class={'str'} style={'str'} bar={1} foo={'str'} onBaz={(val) => {
val; // number
}} />; |
Beta Was this translation helpful? Give feedback.
-
UpdateIn order to be consistent with the usage habits of |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Here's a take on this issue with minimal impact on Vue core and its type system. If the component has No runtime nor component metadata change: child component props are still undefined attrs on the wrapper, that are simply inherited. No change to the complex Vue Component type either, as we piggy-back on the existing Props generic argument. With this, during compilation we'd get errors for incorrect types, like for real props. |
Beta Was this translation helpful? Give feedback.
-
It would be useful to define types for them |
Beta Was this translation helpful? Give feedback.
-
To anyone interested: I might have a workaround that provides strong |
Beta Was this translation helpful? Give feedback.
-
Summary
Allowing to infer attrs by using
attrs
option ofdefineComponent
ordefineCustomElement
.And in the
setup-script
, passing generic type in thedefineAttrs<T>
will also inferattrs
toT
.Basic example
Using
defineComponent
Options Api
Composition Api
Functional Components
Using
defineAttrs<T>
insetup-script
Complie Output:
Using
defineCustomElement
Motivation
This proposal is mainly to infer
attrs
usingdefineComponent
.When using typescript in Vue3, the fallthrough attributes is unable to be used. It's not appropriate obviously that only one can be chosen from
typescript
andFallthrough Attributes
. In most cases, we choosetypescript
and set attributes toprops
option instead of using the fallthrough attributes.Main scenes:
1. Wrapping a native HTML element in a new component, such as
img
.2. Wrapping a component from UI library in a new component, such as
el-button
fromelement-plus
.Unresolved questions
Naming suggestions or improvements on the API are welcome.
Beta Was this translation helpful? Give feedback.
All reactions