如何让TypeScript函数返回显式指定类型+隐式额外属性?
TypeScript函数返回值类型约束问题
示例代码
function system(): ISavable & ISerializable { return { num: 1, // 报错! save() {}, load() {}, serialize() {}, deserialize() {}, } } interface ISavable { save: () => void load: () => void } interface ISerializable { serialize: () => void // 注:原代码此处拼写错误为seriailze,已修正 deserialize: () => void }
问题说明
当返回num: 1这个属性时,TypeScript会报错,提示该属性未在ISavable或ISerializable中定义,这符合预期。
一种可行方案是创建包含所有返回内容的额外类型,但希望函数的独有属性可以隐式推导。
更明确地说:不指定函数返回类型时,TypeScript会自动推导类型并提供自动补全等功能,想要在这个基础上,同时保证必须返回某些显式指定的属性。
需求
希望为函数返回值定义类型,要求:
- 必须返回
ISavable和ISerializable两个接口的所有属性 - 同时允许自由返回该函数独有的额外属性
请问:
- 这是否可行?
- 如果可行,该如何实现?
注:已知通过类可以实现需求,但寻求针对函数的解决方案。
解决方案
完全可行。
可以通过泛型函数+类型约束实现,让TypeScript既强制检查必须实现的接口,又能自动推导额外属性的类型,具体有两种常用方式:
方式一:泛型约束直接应用于函数返回值
定义泛型函数,让返回类型继承自ISavable & ISerializable,TS会自动推导额外属性,同时约束必须实现两个接口的所有成员:
function system<T extends ISavable & ISerializable>(): T { return { num: 1, save() {}, load() {}, serialize() {}, deserialize() {}, } as T } // 调用后自动推导返回类型包含所有属性,支持自动补全 const sys = system() sys.num // 类型为number sys.save() // 正常调用
方式二:通过参数传递推导返回值类型(无类型断言)
如果不想使用类型断言,可以让函数接收符合约束的对象参数,TS会自动推导返回值的完整类型:
function createSystem<T extends ISavable & ISerializable>(obj: T): T { return obj } const sys = createSystem({ num: 1, save() {}, load() {}, serialize() {}, deserialize() {}, }) // sys的类型自动推导为包含num、save、load等所有属性,同时TS会检查是否满足接口约束
注意事项
- 原代码中
ISerializable接口的serialize存在拼写错误(写成seriailze),这会导致即使实现了对应方法也会触发类型错误,需先修正该拼写问题。
内容的提问来源于stack exchange,提问作者Guilherme Oderdenge
相关产品推荐
相关产品推荐

