我有以下接口来定义一个表的列:
export interface IColumnDefinition<TRow, TField extends keyof TRow> {
field: TField;
label?: string;
formatter?: (value: TRow[TField], row: TRow) => string;
}
现在我想要的只是提供行的类型( TRow
),并让TypeScript根据 field
属性中的值自动推断字段的类型( TField
) .
现在假设我的行有以下界面:
interface User {
name: string;
birthDate: number;
}
我尝试的是以下内容:
const birthDateColumnDefinition: IColumnDefinition<User> = {
field: 'birthDate',
formatter: value => new Date(value).toDateString(),
}
这给了我以下错误:
泛型类型'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(),
});
这给了我一个类似的错误:
例外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(),
});
这确实有效,但这不是一个选项,因为我在定义列时实际上没有一行 .
那么有没有办法使这项工作(最好是通过使用接口,而不是一个功能)?
2 回答
这看起来非常类似于partial type inference,在typescript中目前不支持,并且不清楚这个特定用例是否会支持它 .
但是有一件事你可以做 - 你可以有一个函数接受
TRow
的显式类型参数,并返回另一个函数,它将从其参数推断TField
. 语法有点笨拙,但它有效:要使用它,不使用任何参数调用
columnDefinition<User>()
,然后立即使用列定义对象作为参数调用返回的函数:我最终使用artem的答案来编写列定义构建器类:
这允许使用以下语法来定义列: