перебор "итераций" в Typescript - PullRequest
0 голосов
/ 11 июля 2020

Обновление изменил вопрос в соответствии с комментарием @ CherryDT

Я написал итератор для ключей и значений итерируемого (в смысле Python, где dicts считаются повторяемыми, и я использую Javascript объекты в этом смысле):

type key = any;
type value = any;

function* items(
    iterable: Map<key, value> | Iterable<value> | Object
): IterableIterator<[key, value]> {

    if (iterable instanceof Map) {
        for (const entry of iterable.entries()) {
            yield entry;
        }
    }

    else if (iterable instanceof Array || iterable instanceof String || iterable instanceof Set) {
        let index = -1;
        for (const value of iterable) {
            yield [++index, value];
        }
    }

    else if (iterable instanceof Object) {
        for (const entry of Object.entries(iterable)) {
            yield entry;
        }
    }

    else {
        //@ts-ignore
        throw new Error(`Not implemented for ${iterable.constructor.name} type`);
    }
}

Может Избавиться от ошибки без использования комментария // @ts-ignore? Ошибка Property 'constructor' does not exist on type 'never'. Не знаю, как это исправить.

1 Ответ

0 голосов
/ 11 июля 2020

Я избавился от ошибки, улучшив последнюю ветку else. Этот ответ помог. Typescript выдает ошибку, потому что простые типы, такие как number, не имеют конструктора, поэтому instanceof или <simple type>.constructor.name не будут работать, а typeof <simple type> будет.

function* items(
    iterable: Map<key, value> | Iterable<value> | Object
): IterableIterator<[key, value]> {

    if (iterable instanceof Map) {
        for (const entry of iterable.entries()) {
            yield entry;
        }
    }

    else if (
        // sorted by usage frequency
        iterable instanceof Array
        || typeof iterable === 'string'
        || iterable instanceof Set
        || iterable instanceof String
    ) {
        let index = -1;
        for (const value of iterable) {
            yield [++index, value];
        }
    }

    else if (iterable instanceof Object) {
        for (const entry of Object.entries(iterable)) {
            yield entry;
        }
    }

    else {
        throw new Error(`Can not be used with '${typeof iterable}' type`);
    }
}

Пример использования (при компиляции в Javascript):

function* items(iterable) {
    if (iterable instanceof Map) {
        for (const entry of iterable.entries()) {
            yield entry;
        }
    }
    else if (
        // sorted by usage frequency
        iterable instanceof Array
        || typeof iterable === 'string'
        || iterable instanceof Set
        || iterable instanceof String
    ) {
        let index = -1;
        for (const value of iterable) {
            yield [++index, value];
        }
    }
    else if (iterable instanceof Object) {
        for (const entry of Object.entries(iterable)) {
            yield entry;
        }
    }
    else {
        throw new Error(`Can not be used with '${typeof iterable}' type`);
    }
}

let iterables = [
    'hi',
    new String('ho'),
    [1, true, 'blurp'],
    new Set(['foo', 'bar', 'foo']),
    {1:'foo', 'bar':null},
    new Map([[1,'foo'], ['bar', null]]),
];

for (const iterable of iterables) {
    console.log(iterable.constructor.name);
    for(const [key, value] of items(iterable)) {
        console.log(key, value);
    }
}
...