如何在 TypeScript 中合并两个函数定义?

How can I merge two function definitions in TypeScript?

我有以下create函数,它有两个定义:

// Definition 1
export async function create<Entity>(
  entity: ObjectType<Entity>,
  data: DeepPartial<Entity>
): Promise<Entity>;

// Definition 2 
export async function create<Entity>(
  entity: ObjectType<Entity>,
  data: DeepPartial<Entity>,
  pickValues: keyof Entity
): Promise<Partial<Entity>>;

// Implementation
export async function create<Entity>(
  entity: ObjectType<Entity>,
  data: DeepPartial<Entity>,
  pickValues?: keyof Entity
): Promise<Entity | Partial<Entity>> {
  const { manager } = await connectDatabase();

  const instance = manager.create(entity, data);
  const createdEntity = await manager.save(instance);

  return typeof pickValues === 'undefined'
    ? createdEntity
    : pick(createdEntity, pickValues);
}

有没有办法在函数实现的类型中合并这两个定义?也许有条件 return 类型...像这样的东西:

A extends B ? c : d;

确实可以为此使用条件 return 类型。我们需要做的是为 pickValues 参数引入一个通用类型,这样我们就可以将它用于 return 类型:

export async function create<Entity, PickValues extends keyof Entity | undefined = undefined>(
  entity: ObjectType<Entity>,
  data: DeepPartial<Entity>,
  pickValues?: PickValues
): Promise<PickValues extends undefined ? Entity : Partial<Entity>> {
  const { manager } = await connectDatabase();

  const instance = manager.create(entity, data);
  const createdEntity = await manager.save(instance);

  return (typeof pickValues === 'undefined'
    ? createdEntity
    : pick(createdEntity, pickValues as keyof Entity)) as any;
}

不幸的是,由于 TypeScript 的设计限制,它并不真正理解 return 类型应该根据 pickValues (github issue) 的值而有所不同。因此,我们必须将 return 值转换为 any 才能使其正常工作。

由于必要的转换和增加的复杂性,我建议坚持使用重载以获得更好的可读性。


注意:TypeScript 实际上有一个实用程序类型 Pick 可以让您更加具体。您可以在 return 类型中使用 Pick<Entity, Exclude<Values, undefined>> 而不是 Partial<Entity>