【问题标题】:How to use either one of two interfaces in another Typescript interface?如何在另一个 Typescript 接口中使用两个接口之一?
【发布时间】:2020-03-09 13:49:28
【问题描述】:

当我正在学习 Typescript 时,我不确定如何描述这一点。

我面临的问题如下。应用程序中有两个接口。一篇用于博客文章,一篇用于活动文章:

type Category = "Foo" | "Bar";

// 1
export interface PostBlog {
  title: string;
  author: string;
  categories: Array<Category>;
}

// 2
export interface PostEvent {
  title: string;
  date: Date;
}

现在传递给组件的数据如下所示:

import Blogs from "./Blogs";
import Events from "./Events";

const blogPosts = [{ document: { data: { title: "Blogpost title", author: "John Doe" } }, slug: "./blogpost-title" }];
const eventPosts = [{ document: { data: { title: "Event title", date: "01-01-2020" }}, slug: "./event-title" }];

export default function App() {
  return (
    <div className="App">
      <Blogs posts={blogPosts} />
      <Events posts={eventPosts} />
    </div>
  );
}

然后在组件中:

import * as React from "react";

import { Data } from "../shared.types";

interface BlogPosts {
  posts: Data[];
}

const Blogs: React.FC<BlogPosts> = ({ posts }) => {
  return (
    <ul>
      {posts.map(({ document: { data } }) => (
        <li>
          Title: {data.title}
          Author: {data.author} // produces the error
        </li>
      ))}
    </ul>
  );
};

export default Blogs;

所以尝试是:

export interface Data {
  document: {
    data: PostBlog | PostEvent; // use it here
    isEmpty?: boolean;
    excerpt?: string;
  };
  slug: string;
}

但是,Typescript 通知这是不允许的,因为它们具有不共同的属性:

Property 'author' does not exist on type 'PostBlog | PostEvent'.
  Property 'author' does not exist on type 'PostEvent'.ts(2339)

Sandbox example.

【问题讨论】:

    标签: reactjs typescript


    【解决方案1】:

    您可以在通用Data 中定义BlogDataEventData 接口:

    // shared.types.ts
    export interface BlogData {
      title: string;
      author: string;
    }
    
    export interface EventData {
      title: string;
      date: string;
    }
    
    export interface Data<T> {
      document: {
        data: T;
        isEmpty?: boolean;
        excerpt?: string;
      };
      slug: string;
    }
    
    
    // Blogs.tsx
    import { Data, BlogData } from "../shared.types";
    
    interface BlogPosts {
      posts: Data<BlogData>[];
    }
    
    // Events.tsx
    import { Data, EventData } from "../shared.types";
    
    interface EventPosts {
      posts: Data<EventData>[];
    }
    

    Sandbox

    有关泛型的更多信息,请参阅the handbook (archive)。

    【讨论】:

      猜你喜欢
      • 2023-01-10
      • 1970-01-01
      • 1970-01-01
      • 2018-12-01
      • 2019-04-06
      • 1970-01-01
      • 2021-09-10
      • 2011-06-26
      • 1970-01-01
      相关资源
      最近更新 更多