为什么打字稿会与联合类型混淆

问题描述 投票:0回答:1

我正在使用 Typescript 在 React 中创建 Select 组件。这是代码:

type GenericSelectProps = {
  values: (Book | Movie)[];
  onChange: (value: Book | Movie) => void;
};

export const GenericSelect = ({ values, onChange }: GenericSelectProps) => {
  const onSelectChange = (e) => {
    const val = values.find((value) => value.id === e.target.value);

    if (val) onChange(val);
  };

  return (
    <select onChange={onSelectChange}>
      {values.map((value) => (
        <option key={value.id} value={value.id}>
          {value.title}
        </option>
      ))}
    </select>
  );
};

export type Book = {
  id: string;
  title: string;
  author: string;
};

export type Movie = {
  id: string;
  title: string;
  releaseDate: string;
};

const books: Book[] = [
  {
    id: "1",
    title: "Good omens",
    author: "Terry Pratchett & Neil Gaiman"
  },
  {
    id: "2",
    title: "The Truth",
    author: "Terry Pratchett"
  }
];

当我尝试使用这样的组件时:

<GenericSelect
    onChange={(value) => console.log(value.author)}
    values={books}
  />

然后打字稿显示错误,因为它与混淆,即它是电影还是书籍。但是,如果我们使用类型缩小,那么无论如何都不起作用。

<GenericSelect
    onChange={(value) => {
      if ("author" in value) {
        console.log(value.author); // Only accessible if `value` is a `Book`
      } else {
        console.log(value.title); // Only accessible if `value` is a `Movie`
      }
    }}
    values={books}
  />
reactjs typescript
1个回答
0
投票

使用类型保护对你有用吗?

function isBook(obj: unknown): obj is Book {
   return obj?.author !== undefined
}

您可以像这样在代码中使用它:

<GenericSelect
onChange={(value) => {
  if (isBook(value)) {
    console.log(value.author); // Only accessible if `value` is a `Book`
  } else {
    console.log(value.title); // Only accessible if `value` is a `Movie`
  }
}}
values={books}
/>
© www.soinside.com 2019 - 2024. All rights reserved.