You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建满足含调用与索引签名的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:06:37