Home > Software engineering >  Function overloading with typescript on a react component?
Function overloading with typescript on a react component?

Time:10-12

Take a simple react component

interface MyProps {
  color: string
  name?: string
  height?: number

  isBoy?: boolean

  // only add the following if isBoy is true
  actionHero: string
  nickname: string
}

function MyComponent(props: MyProps){
   ...
}

As you can see, the goal is that actionHero and nickName are required if isBoy is set to true. Otherwise, they aren't used.

I assume this is done via function overloading in typescript but how do you do it in react?

CodePudding user response:

You don't need to overload your component in this case. COnsider this example:

import React from 'react'

type Boy = {
  color: string
  name?: string
  height?: number
  isBoy: false
}

type ExtendedBoy = Omit<Boy, 'isBoy'> & {
  actionHero: string
  nickname: string
  isBoy: true;
}

type Props = Boy | ExtendedBoy;

function MyComponent(props: Props) {
  if (props.isBoy) {
    props.nickname // stirng
  } else {
    props.isBoy // false
  }
  return <div></div>

}

const withBoy = <MyComponent isBoy color="red" actionHero={'batman'} nickname={'qwert'} /> // ok
const withoutBoy = <MyComponent isBoy={false} color="red" /> // ok

Playground

I have used discriminated unions instead function overloading.

BUT, nobody can't stop you if you still want to overload your component:

import React, { FC } from 'react'

type Boy = {
  color: string
  name?: string
  height?: number
  isBoy: false
}

type ExtendedBoy = Omit<Boy, 'isBoy'> & {
  actionHero: string
  nickname: string
  isBoy: true;
}

const MyComponent: FC<Boy> & FC<ExtendedBoy> = (props) => {
  if (props.isBoy) {
    props.nickname // stirng
  } else {
    props.isBoy // false
  }
  return <div></div>

}

const withBoy = <MyComponent isBoy color="red" actionHero={'batman'} nickname={'qwert'} /> // ok
const withoutBoy = <MyComponent isBoy={false} color="red" /> // ok

Playground

Please be aware that intersection of functions produces function overloading FC<Boy> & FC<ExtendedBoy>

If you are interested in typescript validation in react components, see my article and my blog here and here

CodePudding user response:

It's possible since types have no conditional logic and can't depend on each other with but two mapped types instead. One for the optional properties, and one for the required ones.

interface MyProps {
    color: string
    name?: string
    height?: number
    isBoy?: false | null
}

interface MyProperRequired extends MyProps {
    isBoy: true
    // only add the following if isBoy is true
    actionHero: string
    nickname: string
}

function MyComponent(props: MyProps | MyProperRequired) {

}


MyComponent({ color: "red", height: 1, name: "hi", isBoy: true })
  • Related