Issue
During the recent code refactoring, I have a question that I do not understand.
First of all, here’s what I’ve been working on:
// CustomTracks.tsx
import { faList } from '@fortawesome/free-solid-svg-icons';
import styled from 'styled-components';
import Icon from '../../../../components/atom/Icon';
import LinkElement from '../../../../components/atom/LinkElement';
const MenuItem = styled.li`
* {
width: 25px;
height: 25px;
}
Link,
LogoutButton {
padding: 5px;
}
`;
function CustomTracks() {
return (
<MenuItem>
<LinkElement
LinkStyle={undefined}
linkText={<Icon icon={faList} />} // Attributes you want to filter on
title="Favorite track list"
to="/tracks/custom"
/>
</MenuItem>
);
}
export default CustomTracks;
// Link.tsx
import { Link, LinkProps } from 'react-router-dom';
import { StyledComponent } from 'styled-components';
export interface LinkElementProps {
to: string;
linkText: string | JSX.Element; // what actually worked
title?: string;
LinkStyle?: StyledComponent<
React.ForwardRefExoticComponent<
LinkProps & React.RefAttributes<HTMLAnchorElement>
>,
any,
{},
never
>;
}
function LinkElement({ to, title, linkText, LinkStyle }: LinkElementProps) {
return LinkStyle ? (
<LinkStyle to={to} title={title ? title : ''}>
{linkText}
</LinkStyle>
) : (
<Link to={to}>{linkText}</Link>
);
}
export default LinkElement;
I want the linkText property of the Link component to accept only string and Icon components. But as you can see, the type of linkText is string | Since it is JSX.Element, it is designed to allow any component, not just the Icon component.
I don’t know what to do to solve this.
Solution
This is not possible in TypeScript because there is no way to know the type of the object passed, since it all comes down to a JSX.Element
. The only workaround that comes in mind would be to display an error message at runtime, and return null
or something else, like this:
function LinkElement({ to, title, linkText, LinkStyle }: LinkElementProps) {
if (
typeof linkText !== 'string' &&
'type' in linkText &&
linkText.type.name !== Icon.name
) {
console.log('Wrong component type for LinkElement, only accepting Icon!');
return null
}
return LinkStyle ? (
<LinkStyle to={to} title={title ? title : ''}>
{linkText}
</LinkStyle>
) : (
<Link to={to}>{linkText}</Link>
);
}
There is an open issue regarding this here.
Answered By – Mentlegen
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0