我有一个应用程序,我使用json结构来定义表的列。
每个列都有一个key
和label
属性,以及一个可选的transformFunc
属性,该属性接受一个函数来转换要在该列中显示的数据。
这是Column
的类型:
type Column = {
key: string
label: string
transformFunc?: (value: string | number | Date) => string
};
transformFunc
可以接受string
、number
或Date
作为参数。但是,我不能这样正确地输入:
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'
}
我该如何解决这个问题?
我看了一下泛型,但是我不知道怎么做。
一般意义
type Column<T extends string | number | Date> = {
key: string
label: string
transformFunc?: (value: T) => string
};
const col: Column<string> = {
key: 'date',
label: 'Date',
transformFunc: (value) => value.substring(0, 5)
}
由于您的类型定义,transformFunc
必须接受所有的联合类型,因此您不能创建一个transformFunc
只接受一种类型的列。
如果您知道特定列将保存什么类型的数据,则可以在函数中使用类型断言:
const col: Column = {
key: 'date',
label: 'Date',
transformFunc: (value: string | number | Date) =>
(value as string).substring(0, 5)
}
如果不想使用泛型,则联合应该在函数作用域之外
type Column = {
key: string
label: string
transformFunc?:
((value: string) => string) |
((value: number) => string) |
((value: Date) => string)
};
const col: Column = {
key: 'date',
label: 'Date',
transformFunc: (value: string) => value.substring(0, 5)
}
或者,如果您想根据transformFunc的值推断类型,您可以使用辅助函数
type ColumnGeneric<T extends string | number | Date> = {
key: string
label: string
transformFunc?: (value: string | number | Date) => string
}
const columnInferenceBuilder = <
_ extends ColumnGeneric<FunctionProp>,
FunctionProp extends string | number | Date
>(o: {
key: string;
label: string;
transformFunc: (value: FunctionProp) => string
}) => o
const inferredColumn = columnInferenceBuilder({
key: 'date',
label: 'Date',
transformFunc: (value: string) => 'foobar',
})
如果您有一个额外的value
属性,该属性对应于transformFunc参数(或以某种方式与之相关以区分)
// imagine its imported
const importedData = {
key: 'foo',
label: 'Foo',
value: 0
} as const
const inferredColumn2 = columnInferenceBuilder2({
...importedData,
transformFunc: (value) => 'foobar',
// ^? (value: 0) => string
})
在TS Playground上查看这些示例