TypeScript中如何将`object`替换为`Record<string, unknown>`避免类型报错
TypeScript 替换object类型的正确方案
报错根因
两个报错的底层逻辑如下:
@typescript-eslint/ban-types禁用object类型是合理的:object仅能限制入参为非原始类型,既无法推导内部属性类型,也不允许直接读取属性,实用性极低。- 替换为
Record<string, unknown>后触发TS2345报错,是因为interface定义的对象类型默认没有索引签名。TypeScript 出于类型安全考虑,禁止未声明索引签名的interface赋值给带索引约束的类型,避免后续扩展interface时出现不符合索引规则的属性。
可选解决方案
方案1:给interface显式添加索引签名
如果你的interface允许存在任意字符串键的属性,直接声明索引签名即可兼容Record类型:
interface Foo { foo: string; // 索引值类型可以根据业务场景调整,比如统一为unknown、或者联合已有的属性类型 [key: string]: unknown; }
方案2:用type代替interface定义对象类型
如果你的对象类型不需要被继承、扩展,改用type定义的对象类型天然支持赋值给Record<string, unknown>,无需额外声明索引:
type Foo = { foo: string; }
方案3:用泛型约束定义工具函数
如果你的函数需要接收任意对象作为入参,推荐用泛型约束实现,既符合ESLint规则,也能保留完整的类型推导能力:
// 写法1:兼容所有对象类型,不需要提前知道键的类型 function baz<T extends Record<string, unknown>>(obj: T) {} // 写法2:如果不需要读取对象属性,也可以直接用object作为泛型约束,ESLint默认不会拦截这种用法 function baz<T extends object>(obj: T) {}
方案4:调整ESLint规则配置
如果你的函数只需要限制入参为非原始类型,不需要操作内部属性,可以在ESLint配置中放开object类型的禁用限制:
// .eslintrc.json 对应规则配置 { "@typescript-eslint/ban-types": ["error", { "types": { "object": false }, "extendDefaults": true }] }
临时兼容方案
如果只是临时需要兼容旧代码,也可以用类型断言跳过类型检查,不推荐长期使用:
baz(foo as Record<string, unknown>)
内容的提问来源于stack exchange,提问作者user3612643
相关产品推荐
相关产品推荐

