定义通用表。这需要数据和显示方式的架构。这是如何调用它的简化示例。
export class MybindCustomAttribute {
static inject = [Element];
constructor(element){
this.element = element;
}
valueChanged(newValue, oldValue){
this.element.innerHTML += newValue;
}
}
组件类具有以下签名:
<PagedTable
data={[ username: 'rob', logins: 32 ]}
schema={[
{
key: 'username',
customRender: (targetData, row) => fnThatOnlyTakesStrings(targetData)
}
]}
/>
和道具:
class PagedTable<T> extends Component<Props<T>, any>
因此可以正确推断该类的具体类型。
为完整起见,在PagedTable内,单元格的简化呈现功能为:
interface Props<T> {
data: T[] | null | undefined
schema: ColumnDef<T>[]
}
interface ColumnDef<T> {
key?: keyof T
customRender?: <U extends keyof T>(
targetData: T[U],
rowData: T
) => string | JSX.Element
}
我想要的是让renderCell(datum: T, { customRender, key }: ColumnDef<T>) {
if (customRender) {
return customRender(datum[key!], datum, key!)
} else {
return datum[key]
}
}
在使用customRender函数时获得正确的类型。在此设置中,其类型为targetData
,这是错误的。
有没有一种方法可以仅使用架构对象的number | string
属性(保证是数据对象的键)来推断类型?
答案 0 :(得分:1)
我认为您的主要问题是您可能不希望customRender
成为通用函数。并非任何customRender
都可以将T[U]
用作任何 U
,而每个customRender
都希望有特定的< / em> U
。毕竟,(targetData, row) => fnThatOnlyTakesStrings(targetData)
似乎期望targetData
是一个string
,它仅适用于某些 specific 键,对吧?
所以我认为您确实希望ColumnDef
在T
和U
中都是通用的,就像这样:
interface ColumnDef<T, U extends keyof T> {
key?: U
customRender?: (
targetData: T[U],
rowData: T
) => string | JSX.Element
}
这最终需要传播到其他引用ColumnDef
的地方:
interface Props<T, U extends keyof T> {
data: T[] | null | undefined
schema: ColumnDef<T, U>[]
}
class PagedTable<T, U extends keyof T> extends React.Component<Props<T, U>, any> {
renderCell(datum: T, cd: ColumnDef<T, U>) {
if (cd.customRender) {
return cd.customRender(datum[cd.key! as any as U], datum)
} else {
return datum[cd.key!]
}
}
}
(我不确定对renderCell
所做的更改是否必要,或者是否表现出预期的效果,但是我遇到了与参数数量有关的错误,并且我对其进行了修正,直到没有抱怨为止。您应该对其进行更改以适合您的需求。
希望有帮助。祝好运。
答案 1 :(得分:1)
如果我正确理解这一点,那么棘手的方面是schema
可以有多个ColumnDef
不同类型的密钥,以及每个 {{1} }需要与其ColumnDef
函数相对应。为了让TypeScript为每个customRender
推断和实施不同的类型,您需要将每个ColumnDef
包装在函数调用中。然后我发现我需要显式指定ColumnDef
以便进行推理。希望这不会造成麻烦,因为我认为在实际的应用程序中您已经具有T
的类型定义。这段代码对我有用:
T