I’m trying to write a function that accepts either Iterable<T>
or `AsyncIterable and maps it:
function map<T, U>(
fn: (item: T) => U,
items: Iterable<T> | AsyncIterable<T>,
): Iterable<U> | Iterable<U> & AsyncIterable<U> {
async function* asyncMapper() {
for await (const item of items) {
yield fn(item);
}
}
if (!items[Symbol.iterator]) {
return asyncMapper()
}
return {
*[Symbol.iterator]() {
for (const item of items) {
yield fn(item);
}
},
[Symbol.asyncIterator]: asyncMapper,
};
}
The gist of it is that, if the items implements Symbol.iterator
we will return an iterable that can iterate both synchronously and asynchronously. However if we don’t we will return only the async iterable.
The problem is that I cannot typeguard the existence of Symbol.iterator
because of the error:
error TS7053: Element implicitly has an
any
type because expression of typesymbol
can't be used to index typeIterable<T> | AsyncIterable<T>
.
Does anyone know how to typeguard Symbol.iterator
, or if I’m doing something wrong here?
Use a user-defined type guard:
Playground link