Проще увидеть, что происходит, если вы измените имена универсальных типов:
export const getArrayFold = <R>(): Foldable<Array<R>> => {
Теперь вы получите Type 'R' is not assignable to type 'A'
.array.reduce
использует различные типы для текущего значения и предыдущего значения, поэтому у вас есть тип A
(универсальный тип из вашего интерфейса) и тип R
из вашей функции getArrayFold
.
У вас нетфактически передается в универсальном типе A
в reduce
, поэтому он считает, что он является A
от интерфейса, что, по сути, означает, что он не может определить, какой тип должен быть.
OneЯ нашел способ сделать это, чтобы ваш интерфейс мог указать тип A
и F
:
export interface Foldable<F, A> {
reduce: (fn: (b: A, a: A) => A, initial: A, foldable: F) => A;
Теперь вы можете написать свою функцию массива как
getArrayFold = <R>(): Foldable<Array<R>, R>
Когда вы звоните, вы можете сделать
getArrayFold<string>().reduce((a, b) => a + b, '', ['hello', 'world']);
Это обеспечит вам безопасность типов, так что вы не сможете использовать 0
в качестве значения или .toFixed
на a
/ b
свойства или тому подобное.