Home > Software design >  How to use TypeScript union types in react
How to use TypeScript union types in react

Time:01-27

I am trying to apply types to ReactJS props as implemented in the following interface. AS you can see the type tags is union type

export interface TagInterface {
  id: number;
  name: string;
}

export interface PostInterface {
  tags: TagInterface[] | string[];
}

I have been able to to successfully use this type in a component inside a function as shown

 onClick={() => handleClick(post.tags[0] as string)}

Now when i try to implement this type on another component TypeScript is throwing an error

Property 'name' does not exist on type 'string | TagInterface'.
  Property 'name' does not exist on type 'string'.
useEffect(() => {
    const getPostData = async () => {
      const { data: posts }: DataInterface = await getRelatedPosts(
        post.tags[0].name // this produces an error
      );
      setRelatedPosts(posts.results);
    };
    getPostData();
  }, []);

How can I properly set the type from the union type?

CodePudding user response:

Property name is not common to string and TagInterface. Thus, you need to have two code paths for two cases:

  • tag is a string
  • tag is a TagInterface

TS will try to analyze your code and give you access to most precise type it inferred. The process is called Narrowing, and in some cases it can be fully transparent, and in some cases you need to check what is the actual type of the object you are dealing with.

In case of string | TagInterface union, the most straightorward approach is a typeof type guard.

interface TagInterface {
  id: number;
  name: string;
}

function getName(tag: TagInterface | string) {
  if (typeof tag === 'string') {
    return tag;
  } else {
    return tag.name;
  }
}

console.log(getName('stringTag'));
console.log(getName({
  id: 1,
  name: 'tagInterfaceTag'
}));

Type assertion that you used in your onclick handler: post.tags[0] as string is not a solution. With this assertion, you force TS to treat tag as a string - it will fail at runtime if it is not.

Playground link

  •  Tags:  
  • Related