我有很多旧的.js
文件,目前无法迁移到.ts
文件。我正在添加.d.ts
文件来添加类型,但是使用类型是一个问题,因为文件通过requireJs相互导入,如下所示:
define(['moduleA', 'moduleB'], function(moduleA, moduleB) {
// ...
});
在这种情况下,我希望正确键入函数参数moduleA
和moduleB
。由于模块名称('moduleA', 'moduleB'
是在运行时配置文件中自定义的,因此TypeScript真的无法帮助连接点。
所以我有一个想法,就是要扩展define
的类型,以便它期望从第一个参数开始的模块名称列表,将它们映射到在映射接口中定义的模块类型,然后键入该函数第二个参数的参数是该模块类型的列表。
我得到了概念工作的基本证明:
/**
* This interface is used to map module names to their types.
*/
export interface RequireJsModules {
foo: boolean;
bar: string;
}
export type RequireJsModulify<T extends string[]> = {
[P in keyof T]: T[P] extends keyof RequireJsModules
? RequireJsModules[T[P]]
: unknown
};
// This line is for testing `RequireJsModulify`.
type Foo = RequireJsModulify<['foo', 'bar', 'wut']>;
此屏幕截图显示RequireJsModulify
正在工作。 Foo
的类型是基于模块名称的元组的正确模块类型的元组。
我受困的是define
函数签名:
declare global {
export function define<T extends string[], U extends RequireJsModulify<T>>(
deps: T,
moduleFactory: ((...args: U) => any)
): void;
}
想法是moduleFactory
的参数必须是基于类型参数T
的映射模块类型,类型参数RequireJsModules
是任意字符串列表。如果字符串是映射接口unknown
的键,则相应的函数参数应具有该模块类型,否则参数应具有describe('requirejs type', () => {
it('should call the module factory with the correct types corresponding to the dependencies', () => {
// There should be no type errors below.
define(['foo', 'bar', 'wut'], function(foo, bar, wut) {
const fooExpected: boolean = foo;
const barExpected: string = bar;
const wutExpected: unknown = wut;
console.log({ fooExpected, barExpected });
});
});
});
类型。
我有这个测试用例:
define
如果foo
的类型按照我想要的方式工作,则第一个参数boolean
的类型应为bar
,第二个参数string
的类型应为{{1 }},而第三个应该是unknown
。
但是目前他们都是unknown
。
因此:
我正在使用TypeScript 3.9.7。
有什么想法为什么不起作用?