0

I'm working with Giphy's API with Typescript and the response give me a mixed media array of objects, something I can summarize like this:

interface Type {
  width: number;
  height: number;
}

interface Image extends Type {
  url: string;
}

interface Video extends Type {
  videoUrl: string;
}

interface Media {
  typeA: Image;
  typeB: Image & Video;
}

I created a getUrl function that allows the user to select the url setting the media type (typeA or typeB) and the url type (url or videoUrl) but, as you can see, not all the combinations are valid (I can't select videoUrl for typeA media).

const getUrl = (media, mediaType: 'typeA' | 'typeB', mediaUrl: 'url', 'videoUrl'): string => {
  return media[mediaType][mediaUrl];
};

This is facing me some typescript errors, like:

Element implicitly has an 'any' type because expression of type '"url" | "videoUrl"' can't be used to index type 'Image | (Image & Video)'. Property 'videoUrl' does not exist on type 'Image | (Image & Video)'.ts(7053)

Can someone help me to improve the type checking and fixing the errors?

Link to codesandbox

2 Answers 2

1

You can slightly change Props interface:

import * as React from "react";

interface Type {
  width: number;
  height: number;
}

interface PropsA {
  mediaType: 'typeA';
  url: "url";
}

interface PropsB {
  mediaType: 'typeB';
  mediaUrl: 'videoUrl';
}

type Props = PropsA | PropsB


interface Image extends Type {
  url: string;
}

interface Video extends Type {
  videoUrl: string;
}

interface Media {
  typeA: Image;
  typeB: Image & Video;
}

const media: Media = {
  typeA: {
    width: 100,
    height: 100,
    url: "my_url_01"
  },
  typeB: {
    width: 100,
    height: 100,
    url: "my_url_02",
    videoUrl: "my_video_url_02"
  }
}

const MyComponent = (props: Props) => {
  const getUrl = () => {

    if (props.mediaType === 'typeA') {
      const x = props; // PropsA
      const { mediaType, url } = props;
      return media[mediaType][url]//[mediaType][mediaUrl];
    }
    const x = props; // PropsB
    const { mediaType, mediaUrl } = props;
    return media[mediaType][mediaUrl];

  };

  return <div>{getUrl()}</div>;
};
Sign up to request clarification or add additional context in comments.

Comments

0

In order for typescript to distinguish union types, you need to type guard it. Can you try the following?

if(mediaType==='typeA') {
  return 'something';
} else {
  return media[mediaType][mediaUrl];
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.