TypeScript联合类型作为函数参数类型不匹配如何解决
问题场景
开发应用时通过JSON结构定义表格列配置:单条列配置包含必填的key、label属性,以及可选的transformFunc属性,该属性接收转换函数,用于处理列内待展示的数据。
初始定义的Column类型如下:
type Column = { key: string label: string transformFunc?: (value: string | number | Date) => string };
设计预期为transformFunc可接收string、number或Date类型作为入参,但编写如下代码时触发TS类型报错:
const col: Column = { key: 'date', label: 'Date', transformFunc: (value: string) => value.substring(0, 5) // TS2322: Type '(value: string) => string' is not assignable to type '(value: string | number | Date) => string' }
报错原因
该报错由TypeScript函数参数的逆变校验规则触发:类型定义中transformFunc需要接收string | number | Date联合类型入参,意味着被赋值的函数必须能安全处理这三类入参。示例中定义的转换函数仅接收string类型,若传入number或Date类型值时调用substring方法会直接抛出运行时错误,因此类型校验不通过。
解决方案
方案1:泛型类型定义(推荐)
给Column增加泛型参数,绑定当前列对应的值类型,transformFunc入参类型直接和泛型关联,同时给泛型设置默认值兼容无明确类型的场景:
// 泛型默认值为原始联合类型,兼容不需要指定具体值类型的配置 type Column<T = string | number | Date> = { key: string label: string transformFunc?: (value: T) => string }; // 明确指定当前列值为string类型,无类型报错 const col: Column<string> = { key: 'date', label: 'Date', transformFunc: (value) => value.substring(0, 5) // value自动推导为string类型 } // 其他值类型的列可正常定义 const amountCol: Column<number> = { key: 'amount', label: 'Amount', transformFunc: (value) => value.toFixed(2) // value自动推导为number类型 }
方案2:函数内部做类型收窄
如果不想修改原有Column类型定义,可以在transformFunc内部通过类型判断收窄值类型,再执行对应逻辑:
const col: Column = { key: 'date', label: 'Date', transformFunc: (value) => { // 先判断值为string类型,再调用字符串方法 if (typeof value === 'string') { return value.substring(0, 5) } // 补充其他类型的处理逻辑 return String(value) } }
注意:请勿使用// @ts-ignore直接忽略该报错,若运行时传入非预期类型的值会直接触发JS运行时异常。
内容的提问来源于stack exchange,提问作者Danny Moerkerke
相关产品推荐
相关产品推荐

