【问题标题】:Typescript type checking with a mixed member types使用混合成员类型进行打字稿类型检查
【发布时间】:2021-04-09 10:44:53
【问题描述】:

我正在使用带有 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 函数,允许用户选择设置媒体类型(typeAtypeB)和 url 类型(urlvideoUrl)的 url,但是,如您所见, 并非所有组合都有效(我无法为 typeA 媒体选择 videoUrl)。

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

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

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

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

Link to codesandbox

【问题讨论】:

    标签: typescript typescript-typings


    【解决方案1】:

    为了让 typescript 区分联合类型,你需要 type 保护它。您可以尝试以下方法吗?

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

    【讨论】:

      【解决方案2】:

      你可以稍微改变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>;
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-11-03
        • 1970-01-01
        • 2021-05-12
        • 2019-07-29
        • 2020-12-25
        • 2019-03-14
        • 1970-01-01
        • 2019-05-26
        相关资源
        最近更新 更多