【问题标题】:TypeScript: Factory function for union typesTypeScript:联合类型的工厂函数
【发布时间】:2021-04-19 22:19:42
【问题描述】:

我有一个自定义的Factory 类型,可以让我创建工厂函数。

export type Factory<T> = (state?: Partial<T>) => T;

我有一个&lt;Avatar /&gt; React 组件,它有一个联合类型作为道具,因为它可以有两个版本(只是图像,或可点击的图像)。换句话说,组件可以有一个或两个属性。

type AvatarOnlyProps = {
  alt: string;
  src: string;
};

type ClickableAvatarProps = {
  alt: string;
  label: string;
  onClick:
    | ((event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void)
    | undefined;
  src: string;
};

export type AvatarProps = AvatarOnlyProps | ClickableAvatarProps;

我想为头像的道具创建一个工厂函数。我试着这样输入:

const createProps: Factory<AvatarProps> = ({
  alt = 'Your avatar',
  label,
  onClick,
  src: source = '/images/default-avatar.png',
} = {}) => ({ alt, label, onClick, src: source });

但是 TypeScript 抱怨:

Property 'label' does not exist on type 'Partial<AvatarOnlyProps> | Partial<ClickableAvatarProps>'.

在工厂函数的参数中。

我怎样才能使错误消失?我怎样才能让 TypeScript 理解,在这个工厂函数中,onClicklabel 都将被提供,或者都不提供?

【问题讨论】:

  • labelAvatarOnlyProps 上不存在,因此尝试解构参数会导致编译器投诉。在尝试访问针对这些类型定义的属性之前,您需要使用 type guards 解析输入参数类型。

标签: typescript typescript-typings factory union-types typescript-types


【解决方案1】:

您不能从联合中解构属性,除非它包含在联合的所有成员中。 labelonClickAvatarOnlyProps 上没有任何定义。

我怎样才能让 TypeScript 理解,在这个工厂函数中,要么提供 onClick 和 label,要么都不提供?

根据您对Factory 的描述,您实际上并非两者兼有或都没有。 FactoryT 接受不完整的 Partial&lt;T&gt; 并返回完整的 T。由于它接受Partial&lt;T&gt;,它似乎可以接受具有label 但不具有onClickPartial&lt;ClickableAvatarProps&gt;,反之亦然。

您正在为altsrc 设置默认值,但不是为labelonClick。因此,如果只提供一个,那么也只会返回一个。

为了正确描述这种行为,我们需要的不仅仅是两种可能性的结合。 createProps 接受具有所有四个属性的对象,其中所有属性都是可选的。它返回一个包含所有四个属性键的对象,其中altsrc 将始终为string,但labelonClick 可能为undefined

我们需要定义返回的对象。这是一种方法:

type AvatarProps = AvatarOnlyProps & Partial<ClickableAvatarProps>;

您现在可以将createProps 定义为Factory&lt;AvatarProps&gt;,不会有任何问题。

【讨论】:

    【解决方案2】:

    我能够通过创建填充最少键的因子函数来解决我的用例:

    const createProps: Factory<AvatarProps> = ({
      alt = 'Your avatar',
      src: source = '/images/default-avatar.png',
      ...props
    } = {}) => ({
      alt,
      src: source,
      ...props,
    });
    

    【讨论】:

      猜你喜欢
      • 2020-02-25
      • 2021-02-07
      • 2019-02-08
      • 1970-01-01
      • 2016-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多