akonsu
akonsu

Reputation: 29576

type must have Symbol.iterator method that returns an iterator

My code below generates an error saying Type 'T | Iterable<T>' must have a '[Symbol.iterator]()' method that returns an iterator. Since I have a check right before the point where the error occurs, I expected to see no error. What else does it need?

function* concat<T extends object>(...args: (Iterable<T> | T | null | undefined)[]) {
    for (const xs of args) {
        if (xs) {
            if (typeof xs[Symbol.iterator] === 'function') {
                for (const x of xs) { // The use of `xs` variable here generates the error.
                    yield x;
                }
            } else {
                yield xs;
            }
        }
    }
}

Upvotes: 1

Views: 2947

Answers (1)

Murolem
Murolem

Reputation: 821

You need to use a type predicate in a separate function as described in this answer.

function* concat<T extends object>(...args: (Iterable<T> | T | null | undefined)[]) {
    for (const xs of args) {
        if (xs) {
            if (isIterable(xs)) {
                for (const x of xs) { // no error
                    yield x;
                }
            } else {
                yield xs;
            }
        }
    }
}

function isIterable(value: unknown): value is Iterable<unknown> {
    return (typeof value === 'object' && value !== null)
        ? typeof value[Symbol.iterator] === 'function'
        : false;
};

Upvotes: 0

Related Questions