kimbaudi
kimbaudi

Reputation: 15575

how to check type in typescript. instance of not working

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

Answers (1)

jacobm
jacobm

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

Related Questions