Как набрать пересечение двух параметров для назначения третьему - PullRequest
2 голосов
/ 07 марта 2019

Я пытаюсь выразить существующий API в TypeScript, и у него есть функция, которая объединяет два параметра в одну форму в качестве третьего параметра.Моя попытка напечатать его до сих пор выглядит так (упрощенно):

type Difference<A, B> = Pick<A, Exclude<keyof A, keyof B>>
export const foo = <Props, A extends Difference<Props, B>, B extends Difference<Props, A>>(
  props: Props,
  a: A,
  b: B,
): Props => ({ ...a, ...b }); // Type 'A & B' is not assignable to type 'Props'.

Props - это желаемая форма, в которую A и B должны объединиться.Моя идея заключалась в том, чтобы сузить A, чтобы расширить от его разницы с B и наоборот, но это приводит к ошибке, замеченной в комментарии, хотя в противном случае она, кажется, ведет себя как ожидалось:

const props = { x: 1, y: 1 };
foo(props, { x: 1, z: 1 }, { y: 1 }); // Valid
foo(props, { x: 1 }, {}); // Error
foo(props, { x: 1, y: 1 }, {}); // Valid

СледуетЯ просто добавляю as unknown as Props утверждение к возвращаемому значению?

1 Ответ

1 голос
/ 07 марта 2019

Вот еще один подход, который может немного сбить с толку пользователя функции, поскольку ошибка находится на входе props.Но он гарантирует, что функция не может быть вызвана, если пересечение не работает.

A & B, поскольку тип возвращаемого значения всегда должен быть подклассом Props, поэтому это не должно вызывать проблем (и приводит к тому, что компиляторне жалуюсь).

export const foo2 = <Props, A, B>(
  props: A & B extends Props ? Props : never,
  a: A,
  b: B,
): A & B => ({ ...a, ...b });

const props = { x: 1, y: 1 };
foo2(props, { x: 1, z: 1 }, { y: 1 }); // Valid
foo2(props, { x: 1 }, {}); // Error
foo2(props, { x: 1, y: 1 }, {}); // Valid
foo2(props, {}, { x: 1, y: 1 }); // Valid
...