首页 > 解决方案 > 使用混合成员类型进行打字稿类型检查

问题描述

我正在使用带有 Typescript 的 Giphy 的 API,响应给了我一个混合媒体对象数组,我可以这样总结:

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;
}

我创建了一个getUrl函数,允许用户选择设置媒体类型 ( typeAor typeB) 和 url 类型 ( url or videoUrl) 的 url,但是,如您所见,并非所有组合都有效(我无法选择videoUrl媒体typeA)。

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

这使我面临一些打字稿错误,例如:

元素隐式具有“任何”类型,因为类型为 '"url" | 的表达式 "videoUrl"' 不能用于索引类型 'Image | (图像和视频)'。“图像 | 类型”上不存在属性“videoUrl” (图像和视频)'.ts(7053)

有人可以帮助我改进类型检查并修复错误吗?

链接到代码沙盒

标签: typescripttypescript-typings

解决方案


您可以稍微更改Props界面:

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>;
};

推荐阅读