-
Notifications
You must be signed in to change notification settings - Fork 96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Functional Components with TypeScript #137
Comments
I have the same questions.Maybe we cannot't use tsx to write a react like Functional Component ,beacuse vue FC's parameter is a context ,not a props. i juse remove the RenderContext type constraints for the context and write props type myself. |
I have a working solution for this, but it's neither pretty nor technically correct 😢 import { RenderContext } from 'vue'
type Maybe<T> = T | undefined | null
type TsxComponent<Props> = (
args: Partial<RenderContext<Props>> & {
[k in keyof Props]: Maybe<Props[k]>
}
) => VueTsxSupport.JSX.Element // or whatever you're using for JSX/TSX interface LabelInputProps {
name: string
type: string
}
const LabeledInput: TsxComponent<LabelInputProps> = ({props}) => {
return (
<div>
<p>{props.name}</p>
<input type={props.type} />
</div>
)
} A warning about this though: This works through a hack, by copying the properties of the type you pass into
This makes them incorrectly appear as argument values outside of If anyone knows how to make this type so that it shows up on the TSX element autocomplete but not in the top-level function params, please post ideas. I think this may not be possible since they have to share a single type definition. |
I decided to refuse such a notation of functional components, since I could not find an elegant solution. I Did everything through import Vue, { RenderContext, VNode, CreateElement, PropType } from 'vue';
import './BaseTitle.sass';
export interface IBaseTitleProps {
level: number;
}
export const BaseTitle = Vue.extend({
functional: true,
props: {
level: {
type: Number as PropType<IBaseTitleProps['level']>,
default: 1,
required: true,
},
},
render(_h: CreateElement, ctx: RenderContext<IBaseTitleProps>): VNode {
const { staticClass, class: cls } = ctx.data;
const { level } = ctx.props;
const HeadingComponent = `h${level}`;
return (
<HeadingComponent class={`title base-title base-title_level-${level} ${staticClass || ''} ${cls || ''}`}>
{ctx.children}
</HeadingComponent>
);
},
}); Autocomplete for props also works fine in latest WebStorm 😊 |
// ...props = {}
const LabeledInput: TsxComponent<LabelInputProps> = ({props = {}}) => {
return (
<div>
<p>{props.name}</p>
<input type={props.type} />
</div>
)
} |
learn from your idea @GavinRay97 type FunctionalProps<Props> = Partial<RenderContext<Props>> & Props;
export type FunctionalComponent<Props = {}> = (
props: FunctionalProps<Props>,
) => JSX.Element;
export function getProps<T>(context: FunctionalProps<T>): T {
return context.props!;
}
const Component: FunctionalComponent<{ a: number; b: string }> = (context) => {
const { a, b } = getProps(context);
return (
<div>
{a}
{b}
</div>
);
};
export const WrapComponent: FunctionalComponent = () => (
<Component a={1} b="" />
); |
HI!✌
I have 2 components. The first looks like this:
And the second one:
I get an error when I pass the prop
level
there.RenderContext
interface.I can rewrite it to something like this
but it also requires me to pass all other fields from
RenderContext
interfaceHow to properly use functional components and TypeScript? Is there any example? Thanks.
The text was updated successfully, but these errors were encountered: