我想定义一个trypescript函数,该函数接受一个字符串并返回一个对象。字符串是使用动态import
或require
导入模块的路径。我希望参数类型比string
更具体,如果字符串不是所需类型的模块的路径,我希望它是类型错误。
factory('./path/to/string-fn'); // should error, () => string not compatible with () => number.
factory('./path/to/number-fn'); // should not error
async function factory(path: T): Promise<number> {
const {default: fn} = await import(path);
return fn()
}
# path/to/string-fn
export default function hello(): string {
return 'hello';
}
# path/to/number-fn
export default function zero(): string {
return 0;
}
type MODULE = typeof import('./path/to/number-fn')
解析为模块的形状,但是type PATH = './path'; type MODULE = typeof import(PATH)
产生错误1141预期的字符串文字。
答案 0 :(得分:0)
您可以这样声明一个类:
export class Path {
constructor(private path: string) {
if (!someTestForValidPath(path)) {
throw new Error('Bad path! Bad!');
}
}
toString(): string {
return this.path;
}
}
然后将其用作工厂功能的参数。
答案 1 :(得分:0)
如果您的路径是事先已知的(即在定义factory
函数时),则可以像下面这样键入函数:
type NumberFunctionPaths = "./path/to/number-fn" | "./path/to/other-number-fn";
async function factory(path: NumberFunctionPaths): Promise<number> {
const {default: fn} = await import(path);
return fn()
}
请注意,如果您从父目录或子目录中调用factory()
,这也将起作用,因为该路径将相对于工厂函数本身保持相对(因为导入位于此处)。
或者,如果您可以将导入本身移动到调用方,则可以这样做:
interface NumberFuncModule {
default: () => number;
}
async function factory(func: Promise<NumberFuncModule>): Promise<number> {
const { default: fn } = await func;
return fn();
}
factory(import("./number-fn"));
factory(import("./string-fn"));
// ^^^^^^^^^^^^^^^^^^^^^ Type '() => string' is not assignable to type '() => number'