TypeScript union作为函数参数



我有一个应用程序,我使用json结构来定义表的列。

每个列都有一个keylabel属性,以及一个可选的transformFunc属性,该属性接受一个函数来转换要在该列中显示的数据。

这是Column的类型:

type Column = {
key: string
label: string
transformFunc?: (value: string | number | Date) => string
};

transformFunc可以接受stringnumberDate作为参数。但是,我不能这样正确地输入:

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上查看这些示例

最新更新