Могу ли я использовать пользовательскую функцию разрешения модуля (например, "proxyquire") вместо require() с TypeScript?

У меня есть файл TypeScript config.ts это будет работать с узлом:

import myDependency = require('my-dependency');    

export = {
    doSomething = () => {
        ...
    }
}

В другом файле TypeScript я могу import этот файл с полным типом безопасности:

import config = require('./config');
config.doSomething();
config.doSomethingElse(); // compiler error, this method doesn't exist

Теперь я хочу протестировать этот скрипт. Для того, чтобы смоделировать зависимости, которые этот скрипт require() s Я использую proxyquire, который позволяет мне указывать значения, которые мой скрипт получит при вызове require(), Вот как может выглядеть мой тест:

import proxyquire = require('proxyquire');
const config = proxyquire('./config', {
    'my-dependency': {} // this mocked object will be provided when config.ts asks for `my-dependency`
});

expect(config.doSomething()).to.do.something();

Это отлично работает, за исключением того, что мой config переменная имеет тип any потому что я использую proxyquire() на месте require(), TypeScript должен дать require() функция специальной обработки, чтобы позволить ему выполнить разрешение модуля. Есть ли способ сказать компилятору TypeScript, что proxyquire() следует также сделать разрешение модуля, аналогично require()?

Я мог бы переписать config.ts как класс или заставить его использовать интерфейс. Тогда я смогу явно указать переменные в моих тестах, импортировав определение класса / интерфейса. Но позволяя proxyquire() неявно печатать вещи для меня было бы гораздо проще.

1 ответ

Существует обходной путь - вы можете получить тип config.ts модуль путем импорта фактического модуля и использования typeof в приведении типа:

import proxyquire = require('proxyquire');

import configType = require('./config');

const config = <typeof configType> proxyquire('./config', {
    'my-dependency': {} // this mocked object will be provided when config.ts asks for `my-dependency`
});

config.doSomething();

// config.noSuchMethod(); // does not compile

Это не идеально, потому что вы должны импортировать один и тот же модуль в тесте дважды - реальный, чтобы получить его тип, и "проксимити", который будет фактически использоваться в ваших тестах, и вы должны быть осторожны, чтобы не перепутать два. Но это довольно просто по сравнению с задачей реализации другого варианта разрешения модуля для машинописи. Кроме того, когда configType используется таким образом - только для набора текста - его импорт даже не появится в сгенерированном коде javacsript.

Другие вопросы по тегам