我有以下接口来定义表的列:
export interface IColumnDefinition<TRow, TField extends keyof TRow> {
field: TField;
label?: string;
formatter?: (value: TRow[TField], row: TRow) => string;
}
Run Code Online (Sandbox Code Playgroud)
现在我想要的是只提供行的类型 ( TRow),让 TypeScriptTField根据field属性中的值自动推断字段的类型 ( ) 。
现在假设我的行有以下界面:
interface User {
name: string;
birthDate: number;
}
Run Code Online (Sandbox Code Playgroud)
我尝试的是以下内容:
const birthDateColumnDefinition: IColumnDefinition<User> = {
field: 'birthDate',
formatter: value => new Date(value).toDateString(),
}
Run Code Online (Sandbox Code Playgroud)
这给了我以下错误:
通用类型 'IColumnDefinition<TRow, TField extends keyof TRow>' 需要 2 个类型参数。
我还尝试过使用函数来创建定义,希望可以从参数中推断出类型:
function createColumnDefinition<TField extends keyof TRow>(
field: TField,
columnDef: Partial<IColumnDefinition<TRow, TField>>): IColumnDefinition<TRow, TField>
{
return {
...columnDef,
field,
};
}
const birthDateColumnDefinition = createColumnDefinition<User>('birthDate', {
formatter: (value, row) => new Date(value).toDateString(),
});
Run Code Online (Sandbox Code Playgroud)
这给了我一个类似的错误:
排除了 2 个类型参数,但得到了 1 个。
但是,如果我还将该行作为参数包含在内,并将所有通用参数一起删除,则它可以正常工作:
function createColumnDefinition<TRow, TField extends keyof TRow>(
row: TRow,
field: TField,
columnDef: Partial<IColumnDefinition<TRow, TField>>): IColumnDefinition<TRow, TField>
{
return {
...columnDef,
field,
};
}
const user: User = {
name: 'John Doe',
birthDate: 549064800000,
};
const birthDateColumnDefinition = createColumnDefinition(user, 'birthDate', {
formatter: (value, row) => new Date(value).toDateString(),
});
Run Code Online (Sandbox Code Playgroud)
这确实有效,但这不是一个选项,因为在定义列时我实际上没有一行。
那么有什么方法可以使这项工作(最好使用接口而不是函数)?
现在我想要的是只提供行的类型(TRow),并让TypeScript根据字段属性中的值自动推断字段的类型(TField)。
这看起来与typescript 中目前不支持的部分类型推断非常相似,目前尚不清楚这个特定用例是否会支持它。
但是你可以做一件事——你可以让一个函数接受显式类型参数 for TRow,并返回另一个TField将从其参数推断的函数。语法有点笨拙,但它有效:
function columnDefinition<TRow>():
<TField extends keyof TRow>(def: IColumnDefinition<TRow, TField>) =>
IColumnDefinition<TRow, TField> {
return <TField extends keyof TRow>(def: IColumnDefinition<TRow, TField>) => def
}
export interface IColumnDefinition<TRow, TField extends keyof TRow> {
field: TField;
label?: string;
formatter?: (value: TRow[TField], row: TRow) => string;
}
interface User {
name: string;
birthDate: number;
}
Run Code Online (Sandbox Code Playgroud)
要使用它,您可以columnDefinition<User>()不带任何参数调用,然后立即以列定义对象作为参数调用返回的函数:
const birthDateColumnDefinition = columnDefinition<User>()({
field: 'birthDate',
formatter: value => new Date(value).toDateString(),
// value inferred as (parameter) value: number
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2153 次 |
| 最近记录: |