如何约束TypeScript函数仅接受兼容空对象的类型?
TypeScript 约束泛型仅接受兼容空对象的类型
问题场景
以下代码可正常运行,空对象能被赋值给Data类型:
export type Data = Record<string, unknown> const x: Data = {}
但在泛型函数中,直接给泛型变量赋值空对象会触发类型错误:
export const createManager = <FormData extends Data>( initial: FormData, ) => { const x: FormData = {}; // TypeScript 报错 }
报错信息:
'{}' is assignable to the constraint of type 'FormData', but 'FormData' could be instantiated with a different subtype of constraint 'Data'.(2322)
问题核心:FormData可能被推断为Data的子类型(比如{ name: string }),这类子类型包含必填属性,空对象无法兼容。需要约束函数仅接受空对象可赋值的FormData类型。
解决方案
方案一:通过条件约束泛型参数
在泛型约束中加入条件判断,筛选出满足{} extends FormData的类型:
export type Data = Record<string, unknown>; export const createManager = <FormData extends ({} extends FormData ? Data : never)>( initial: FormData, ) => { const x: FormData = {}; // 不再报错 }; // 测试用例 createManager({}); // 正常通过 createManager({ name: "test" }); // 报错,符合预期({} 无法赋值给 { name: string })
原理:利用条件类型过滤出兼容空对象的类型,不符合条件的会被约束为never,调用时直接触发类型错误。
方案二:使用Partial<Data>作为泛型约束
如果业务场景允许FormData仅包含可选属性,可直接将泛型约束改为Partial<Data>:
export type Data = Record<string, unknown>; export type PartialData = Partial<Data>; export const createManager = <FormData extends PartialData>( initial: FormData, ) => { const x: FormData = {}; // 不再报错 }; // 测试用例 createManager({}); // 正常通过 createManager({ name?: "test" }); // 正常通过 createManager({ name: "test" }); // 报错,符合预期
原理:Partial<Data>会将Data的所有属性转为可选类型,此时空对象能兼容所有该类型的子类型。
内容的提问来源于stack exchange,提问作者pom421
相关产品推荐
相关产品推荐

