TypeScript中`fn(a: AType)`与`fn<T extends AType>(a: T)`哪种更好?
TypeScript两种函数参数写法的差异与选择依据
两种写法在你给出的示例场景下运行效果完全一致,差异只在TS类型系统层面的能力,选择逻辑如下:
核心差异
- 普通接口写法(函数b):参数类型直接固定为
OwnsSth,TS仅校验入参是否符合接口结构,入参的额外属性会被类型擦除,函数内部和返回值都只能识别到OwnsSth定义的属性。 - 泛型约束写法(函数a):仅约束入参必须满足
OwnsSth的结构,会完整保留入参的原始类型,函数内部操作、返回值都可以继承入参的完整类型信息。
举个简单的对比示例就能看出区别:
// 普通写法返回值 function b(b1: OwnsSth) { console.log(b1.sth) return b1 } const resB = b(foo) // resB的TS类型为OwnsSth,访问resB.sthElse会报类型错误,丢失了原始对象的额外属性类型 // 泛型写法返回值 function a<T extends OwnsSth>(a1: T) { console.log(a1.sth) return a1 } const resA = a(foo) // resA的TS类型为 { sth: number, sthElse: string },可以正常识别原始对象的所有属性类型
选择依据
- 优先选普通接口写法(函数b):如果你的逻辑只是消费接口定义的属性,不需要保留入参的额外类型、也不需要返回和入参原始类型关联的值,这种写法更简洁,没有额外的心智负担。
- 必须选泛型约束写法(函数a):如果满足以下任意一种场景:
- 函数需要返回入参本身,且要保留入参的完整类型信息
- 函数内部需要操作入参的额外属性,且需要TS做类型校验
- 存在多个参数,参数之间的类型需要关联约束(比如第二个参数的可选值只能是第一个参数的某个属性的值)
你给出的示例场景下两种写法都可以,普通写法更合适。
内容的提问来源于stack exchange,提问作者kspacja
相关产品推荐
相关产品推荐

