возвращая объединение типов из массивов - PullRequest
0 голосов
/ 07 марта 2019

Мне бы хотелось, чтобы этот метод слияния имел возвращаемый тип объединения всех различных типов массивов, переданных в него.

type AnyIterable<T> = Iterable<T> | AsyncIterable<T>

async function* merge<T>(...iterables: Array<AnyIterable<T>>) {
  for (const iterable of iterables) {
    yield* iterable
  }
}

merge([1, 2, 3], ['1', '2', '3'])
// Argument of type 'string[]' is not assignable to parameter of type 'AnyIterable<number>'.
// Property '[Symbol.asyncIterator]' is missing in type 'string[]' but required in type 'AsyncIterable<number>'.ts(2345)

Но я получаю эту ошибку.Очевидно, что это ожидаемо, но я не знаю, как набрать это, чтобы получить значения из массива итераций.

1 Ответ

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

Хм, я думаю, что люди обычно хотят, чтобы подобные ошибки происходили , так как гетерогенные массивы встречаются реже, чем однородные массивы, и вывод типа, который всегда расширялся до тех пор, пока не работал, не улавливает реальных ошибок.

Если вы хотите обойти это, можно пойти в другом направлении: заставить вывод типа выполнить успешно, а затем вычислить значение T из него, если вам это нужно:

async function merge<I extends Array<AnyIterable<any>>>(...iterables: I) {
  for (const iterable of iterables) {
  }
}

type UnArrayAnyIterable<A extends Array<AnyIterable<any>>> = 
  A extends Array<AnyIterable<infer T>> ? T : never;

Теперь это успешно:

merge([1, 2, 3], ['1', '2', '3']); // I inferred as the tuple `[number[], string[]]`

И если вы хотите T, вы можете использовать UnArrayAnyIterable:

declare function foo<I extends Array<AnyIterable<any>>>(...iterables: I): UnArrayAnyIterable<I>;
const ret = foo([1, 2, 3], ['1', '2', '3']); // string | number

Хорошо, надеюсь, это поможет.Удачи!

...