I'm trying to write a variadic zip over iterables while also preserving type. For example,
function* naturals(max=10) { for (let i=0; i<max; i++) yield i }
const x = [1, 2, 3]
const y = ["a", "b", "c"]
const zipped = zip(naturals(), x, y)
console.log([...zipped]) // => [[0, 1, "a"], [1, 2, "b"], [2, 3, "c"]]
function* zip<?>(...iterables:?[]) {
const iterators = iterables.map(iter => iter[Symbol.iterator]())
...
}
Is there a type signature which helps preserve my types?
You could give
zip()the following call signature:It is generic in the type parameter
Trepresenting the type of the arrays in each element of the output (i.e., the function returnsIterable<T>). This is expected to be a tuple type.The input type is a rest parameter of a mapped type over the array/tuple type
T, where each element ofTis wrapped inIterable. This mapped type is homomorphic (featuringin keyof T, see What does "homomorphic mapped type" mean? for more info) and so TypeScript can inferTfrom it.Let's try it on your example:
Here
iterablesis of a tuple type assignable to[Iterable<number>, Iterable<number>, Iterable<string>], and so the compiler infersTas[number, number, string]. So the output type isIterable<[number, number, string]>as expected.Playground link to code