
Handling default `as` attributes
Handling default `as` attributes 관련
Consider again our current solution:
export const Text = <C extends React.ElementType>({
as,
children,
...restProps
}: TextProps<C>) => {
const Component = as || "span"; // 👈 look here
return <Component {...restProps}>{children}</Component>;
};
Particularly, pay attention to where a default element is provided if the as prop is omitted.
const Component = as || "span"
This is properly represented in the JavaScript world by implementation: if as is optional, it’ll default to a span.
The question is, how does TypeScript handle this case when as isn’t passed? Are we equally passing a default type?
Well, the answer is no, but below’s a practical example. Let’s say you went ahead to use the Text component as follows:
<Text>Hello Text world</Text>
Note that we’ve passed no as prop here. Will TypeScript be aware of the valid props for this component?
Let’s go ahead and add an href:
<Text href="https://www.google.com">Hello Text world</Text>
If you go ahead and do this, you’ll get no errors. That’s bad.
A span should not receive an href prop / attribute. While we default to a span in the implementation, TypeScript is unaware of this default. Let’s fix this with a simple, generic default assignment:
type TextProps<C extends React.ElementType> = {
as?: C;
children: React.ReactNode;
} & React.ComponentPropsWithoutRef<C>;
/**
* See default below. TS will treat the rendered element as a
span and provide typings accordingly
*/
export const Text = <C extends React.ElementType = "span">({
as,
children,
...restProps
}: TextProps<C>) => {
const Component = as || "span";
return <Component {...restProps}>{children}</Component>;
};
The important bit is highlighted below:
<C extends React.ElementType = "span">
Et voilà! The previous example we had should now throw an error when you pass href to the Text component without an as prop.
The error should read: Property 'href' does not exist on type ....
