Ошибка машинописного текста : Тип 'number' не может быть назначен типу 'never' - PullRequest
1 голос
/ 08 мая 2020
interface Opts {
  onFrame: () => void;
  onAudioSample: null;
  emulateSound: boolean;
  sampleRate: number;
}

class NES {
    constructor(opts: Opts) {
        this.opts = {
            onFrame() { },
            onAudioSample: null,
            emulateSound: true,
            sampleRate: 44100,
        }

        if (typeof opts !== "undefined") {
            let key: keyof Opts
            for (key in this.opts) {
                if (typeof opts[key] !== "undefined") {
                    // got err here
                    this.opts[key] = opts[key];
                }
            }
        }
    }
    opts: Opts
}

вы можете обмануть ошибку на игровой площадке TS : здесь

машинописный текст: v3.8.3 err: Type 'number' не назначается типу never. Я не понимаю, почему это тип never.

Ответы [ 3 ]

2 голосов
/ 08 мая 2020

Вы получаете эту ошибку, потому что TypeScript не может сделать вывод, что this.opts[key] и opts[key] относятся к одному типу. Если бы вы должны были покрыть каждую половину =:

  • opts[key] могло бы быть Function, null, boolean или number
  • this.opts[key] должен получить Function, null, boolean или number в зависимости от значения key, которого мы не знаем
  • единственный общий супертип для Function, null, boolean и number это never, так что это тип, который TypeScript хочет для this.opts[key]

Интересно, если бы вы извлекли это с анонимной функцией generi c, она работает: в рамках одного присваивания Typescript может вывести и использовать тип Opts[K]. jcalz предлагает аналогичное решение в этот аналогичный вопрос .

if (typeof opts[key] !== "undefined") {
  // this.opts[key] = opts[key];
  (<K extends keyof Opts>(k: K) => { this.opts[k] = opts[k]; })(key);
}

игровая площадка машинописного текста

Тем не менее, я бы используйте оператор распространения, как в Muke sh Soni, ответ , завершив присвоение this.opts ...opts, или используйте Object.assign. Существует небольшой риск того, что переданный opts содержит дополнительные ключи, но Typescript должен гарантировать обратное во время компиляции. (В этом отношении, если вы ожидаете, что opts будет необязательным и потенциально неполным, его, вероятно, следует определить как opts?: Partial<Opts>.)

class NES {
    constructor(opts?: Partial<Opts>) {
        this.opts = Object.assign({
            onFrame() { },
            onAudioSample: null,
            emulateSound: true,
            sampleRate: 44100,
        }, opts);
    }
    opts: Opts
}

См. Также: Разброс объекта по сравнению с Object.assign , в котором отмечается, что решения очень похожи и оба применимы для значений параметров по умолчанию.

1 голос
/ 08 мая 2020

Я не знаю, почему вы получаете эту ошибку. Еще один способ объединить оба варианта - использовать операторы распространения.

this.opts = {
            onFrame() { },
            onAudioSample: null,
            emulateSound: true,
            sampleRate: 44100,
            ...opts
        };
0 голосов
/ 08 мая 2020

Если вы поместите as any после доступа к свойству, TypeScript проверит, что key является допустимым ключом

if (typeof opts[key] !== "undefined") {
  (this.opts[key] as any) = opts[key];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...