如何在.d.ts文件中为带多个可调用属性的函数定义TS类型
正确类型声明实现方案
你原有写法存在三个核心问题:
- 类型别名定义语法错误,TS中类型别名赋值用
=而非: - 命令列表没有保留精确的字符串字面量类型,TS无法识别具体存在哪些挂载属性
- 宽泛的字符串索引签名会让TS判定任意字符串属性都合法,无法输出精确的类型提示,也不会对错误属性名做校验
完整实现代码
// 定义入参类型,可根据实际业务逻辑收窄类型 type ArgsType = string | object; // 以只读元组形式定义命令列表,保留每个命令的精确字符串字面量 const COMMAND_LIST = [ "run-like-nuts", "some-more-commands", "another-nice-command", "power-commmand", // 后续新增命令直接追加到该数组即可,类型会自动同步 ] as const; // 提取所有命令的联合类型 type Command = typeof COMMAND_LIST[number]; // 定义commandRunner的基础调用签名 type BaseCommandRunner = (...args: ArgsType[]) => Promise<string>; // 映射生成所有挂载在函数上的命令方法类型 type MountedCommandMethods = { [K in Command]: (...args: ArgsType[]) => Promise<string>; }; // 交叉基础类型和挂载方法类型,得到最终类型并导出 declare const commandRunner: BaseCommandRunner & MountedCommandMethods; export default commandRunner;
实现说明
- 给命令列表加
as const断言后,TS不会把数组元素类型宽泛推导为string,而是保留每个元素的精确字符串字面量,通过typeof COMMAND_LIST[number]即可得到所有命令名的联合类型。 - 映射类型
[K in Command]会遍历命令联合类型的每一个成员,生成和命令同名的属性,每个属性对应JS中动态挂载的方法签名,TS会自动识别所有存在的挂载属性,输入时给出补全提示,输错命令名时会直接抛类型错误。 - 交叉类型组合了函数本身的调用签名和挂载属性的类型,既支持直接调用
commandRunner,也支持调用挂载的命令方法,两种调用方式都会有正确的类型校验和提示。
内容的提问来源于stack exchange,提问作者atifcppprogrammer
相关产品推荐
相关产品推荐

