Могу ли я использовать пользовательскую функцию разрешения модуля (например, "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.