TypeScript:联合类型的工厂函数

TypeScript: Factory function for union types

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

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

我有一个 <Avatar /> React 组件,它有一个联合类型作为 prop,因为它可以有两个版本(只是图像,或可点击的图像)。换句话说,组件可以有 或 props。

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,要么都不提供?

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

How can I get TypeScript to under stand, that in this factory function either both onClick and label will be supplied, or neither?

根据您对 Factory 的描述,实际上并不是两者都有或两者都没有的情况。 TFactory 需要一个不完整的 Partial<T> 和 returns 一个完整的 T。因为它接受 Partial<T> 它似乎可以接受 Partial<ClickableAvatarProps>label 但没有 onClick,反之亦然。

您正在为 altsrc 设置默认值,但没有为 labelonClick 设置默认值。所以如果只提供一个,那么也只返回一个。

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

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

type AvatarProps = AvatarOnlyProps & Partial<ClickableAvatarProps>;

您现在可以将 createProps 定义为 Factory<AvatarProps>,您不会有任何问题。

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

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