我正在为用JavaScript编写的库创建一个typescript声明文件,对于这个任务,我一遍又一遍地遇到一个问题。JavaScript库在许多地方重复了以下模式。
const commandList = [
"run-like-nuts",
"some-more-commands",
"another-nice-command",
"power-commmand",
// lots more commands like this
// in this list
];
function commandRunner(...args) {
// Does some internal work based on ...args
// returns type Promise<string>
}
commandList.forEach(command => {
Object.defineProperty(commandRunner, command, {
value: function(command, ...args) {
return commandRunner(command, ...args);
}
));
});
我如何为commandRunner
函数定义类型,以便当我在typescript中使用它时,它是可调用的,并且它在commandList
中具有属性,从上面的例子中可以明显看出,这也成为可调用的。
type ArgsType: string | Object;
type commandList = [
"run-like-nuts",
"some-more-commands",
"another-nice-command",
"power-commmand",
// lots more commands like this
// in this list
];
export default (function commandRunner(...args: ArgsType[]) {}) & {
[command: Command]: (command: Command,...args: ArgsType[]) => Promise<string>
}
你应该保持commandList
作为一个数组,这样我们可以在运行时和编译时使用它。要使字符串字面值可用于键入,我们必须使用as const
来定义它。
const commandList = [
"run-like-nuts",
"some-more-commands",
"another-nice-command",
"power-commmand",
// lots more commands like this
// in this list
] as const;
对于commandRunner
类型,可以映射到commandList
中的字符串字面值。
type CommandRunner = ((...args: ArgsType[]) => Promise<string>) & {
[Command in typeof commandList[number]]:
(command: Command,...args: ArgsType[]) => Promise<string>
}
游乐场