Reputation: 608
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?
Upvotes: 0
Views: 287
Reputation: 33051
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>;
};
Upvotes: 1
Reputation: 3823
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];
}
Upvotes: 0