You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

TypeScript联合类型引发的类型混淆问题求助

TypeScript联合类型引发的类型混淆问题求助

你好呀,这个问题的核心在于你的GenericSelect组件没有把values的类型和onChange的参数类型做关联,导致TypeScript没办法根据你传入的具体数组自动推断出onChange参数的准确类型——哪怕你用了类型收窄,组件本身的联合类型定义还是会让TS“犯迷糊”。

解决这个问题的关键是用泛型来绑定这两个属性的类型,让TS明确知道:当你传入的是Book[]onChange的参数就一定是Book;如果传入的是Movie[],参数就一定是Movie

来看看修改后的完整代码:

首先保留你的基础类型定义,然后改造组件的类型和实现:

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

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

// 改成泛型Props,让values和onChange的类型绑定
type GenericSelectProps<T extends Book | Movie> = {
  values: T[];
  onChange: (value: T) => void;
};

// 泛型组件实现
export const GenericSelect = <T extends Book | Movie>({ values, onChange }: GenericSelectProps<T>) => {
  // 给事件参数加上明确类型,避免any
  const onSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
    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>
  );
};

现在再使用组件时,TypeScript会自动精准推断类型:

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

// 这里value会被自动推断为Book类型,直接访问author毫无问题
<GenericSelect
  onChange={(value) => console.log(value.author)}
  values={books}
/>

这样不仅不需要再写类型收窄的冗余代码,TS也不会再抛出类型错误啦~

备注:内容来源于stack exchange,提问作者mir 433

火山引擎 最新活动