Как сузить тип generi c с помощью переданной функции защиты? - PullRequest
2 голосов
/ 22 апреля 2020

Давайте рассмотрим Opt из пакета ts-opt (это просто вариант Maybe / Option / Optional) и isNumber для защиты типа ((x): x is number => ...).

Можно ли реализовать (и как) метод someIf обобщенным образом c (работа с защитой произвольного типа, безопасная по типу, без необходимости указания пользователем типа, который уже находится в страже типа):

type A = number | string;
const x: A = 4;
const y: A = 'y';
opt(x)               // Opt<number | string>
  .someIf(isNumber); // Opt<number> (Some(4))
opt(y)               // Opt<number | string>
  .someIf(isNumber); // Opt<number> (None)

1 Ответ

1 голос
/ 22 апреля 2020

Одним из способов достижения этого (без использования someIf в качестве функции-прототипа) является следующая

type A = number | string;

const x: A = 4;
const y: A = "y";

const isNumber = (a: any): a is number => typeof a === "number";

const someIf = <T>(ot: Opt<any>, f: (x: any) => x is T): Opt<T> =>
  ot.caseOf(
    t => (f(t) ? opt(t) : none),
    () => none
  );

const ox = someIf(
  opt(x),
  isNumber
); // Opt<number> <- Some(4)

const oy = someIf(
  opt(y),
  isNumber
); // Opt<number> <- None

Ссылка в песочнице


Идея это довольно просто. Сверните необязательное значение, если none, нам нечего делать. В противном случае проверьте свернутое значение по типу guard. Если защита успешна, просто верните значение (теперь его тип сужен), иначе верните none.

...