Reputation: 15575
I am trying to convert a simple custom Link component in React to use TypeScript.
Here is the simple Link component in JavaScript:
import React from "react";
import { Link as RouterLink } from "react-router-dom";
import styled from "@emotion/styled";
const StyledLink = styled(RouterLink)`
color: blue;
`;
const StyledAnchor = styled.a`
color: red;
`;
export default function Link(props) {
return Boolean(props.to) ? (
<StyledLink {...props} />
) : (
<StyledAnchor {...props} />
);
}
And here is usage of the above component:
import React from 'react'
import Link from 'components/Link'
export default function Demo() {
return (
<>
<Link href="https://stackoverflow.com">external link</Link>
<br />
<Link to="/">internal link</Link>
</>
)
}
But I'm having problems converting the above Link component to use TypeScript.
Here is what I have so far in TypeScript:
import { AnchorHTMLAttributes } from 'react'
import { Link as RouterLink, LinkProps } from 'react-router-dom'
import styled, { StyledComponent } from '@emotion/styled'
import { EmotionJSX } from '@emotion/react/types/jsx-namespace'
type AnchorProps = AnchorHTMLAttributes<HTMLAnchorElement>
const StyledLink: StyledComponent<LinkProps> = styled(RouterLink)`
color: blue;
`
const StyledAnchor: StyledComponent<AnchorProps> = styled.a`
color: red;
`
export default function Link(
props: LinkProps | AnchorProps
): EmotionJSX.Element {
if (/* HOW TO CHECK IF props IS LinkProps or AnchorProps */) {
return <StyledLink {...props} />
} else {
return <StyledAnchor {...props} />
}
}
So how can I find out whether props
is of type LinkProps
or AnchorProps
in Typescript?
I already tried instanceof
but I get an error 'LinkProps' only refers to a type, but is being used as a value here
:
export default function Link(
props: LinkProps | AnchorProps
): EmotionJSX.Element {
if (props instanceof LinkProps) {
return <StyledLink {...props} />
} else {
return <StyledAnchor {...props} />
}
}
Upvotes: 0
Views: 210
Reputation: 14035
TypeScript won't allow you to directly do an instanceof
check, but there's a trick you can use to get what you want. LinkProps
is an interface that requires certain fields to be present, and AnchorProps
requires different fields. So if you check for the presence of, say, to
(a field that only exists on LinkProps
), then TypeScript will know that if the check succeeds then props
is a LinkProps
and if it fails then props
is an AnchorProps
.
So for your example, you could write:
export default function Link(
props: LinkProps | AnchorProps
): EmotionJSX.Element {
if ('to' in props) {
return <StyledLink {...props} />
} else {
return <StyledAnchor {...props} />
}
}
Upvotes: 1