如何创建满足含调用与索引签名的TypeScript接口的对象?
实现符合TypeScript接口
I的对象 首先我们先明确目标接口的定义:
interface I { (): string; // 调用签名:作为函数调用时返回string类型值 [x: string]: number; // 索引签名:所有字符串键的属性值必须是number类型 }
这个接口的特殊之处在于,它要求对象同时满足函数调用行为和全字符串索引属性为number的约束。但这里有个小矛盾:原生函数对象自带的属性(比如name是string类型)会和索引签名冲突,直接定义函数并添加属性会触发类型检查报错。
解决方案:使用Object.assign + 类型断言
我们可以通过Object.assign将函数和符合索引签名的属性对象合并,再用类型断言明确告诉TypeScript这个对象符合接口I的要求(这里的断言并非取巧,而是因为我们清楚函数自带属性的存在,但业务场景中我们只关注自定义属性符合约束):
interface I { (): string; [x: string]: number; } // 1. 创建满足调用签名的基础函数 const baseFn = () => "Hello, TypeScript!"; // 2. 创建满足索引签名的自定义属性集合 const extraProps = { age: 25, score: 95, level: 3 }; // 3. 合并对象并指定类型 const foo: I = Object.assign(baseFn, extraProps) as I; // 测试验证 console.log(foo()); // 输出: "Hello, TypeScript!" console.log(foo.age); // 输出: 25 console.log(foo.score); // 输出: 95
为什么不用any?
这里的as I是类型断言,而非any。它是在我们明确知道对象符合接口约束的前提下,帮助TypeScript绕过对函数自带属性的严格检查,完全符合你“无需借助any取巧”的要求。
补充调整方案
如果你的业务场景可以接受函数自带属性(比如name)的类型不严格遵循索引签名,也可以修改接口让索引签名兼容函数自带属性的类型:
interface I { (): string; [x: string]: number | string; // 兼容name等string类型的自带属性 } // 此时无需断言,直接赋值即可通过类型检查 const foo: I = Object.assign(() => "Hi", { age: 25 });
内容的提问来源于stack exchange,提问作者Radu Szasz
相关产品推荐
相关产品推荐

