用于通用T的类型声明可能是或可能不是分层的?

时间:2018-06-01 01:23:24

标签: reactjs typescript

我正在扩展一个React表(创造性地称为“表”),该表采用通用数据数组以及一些列配置数据,并呈现表。声明如下:

export class Table<T> extends React.Component<TableProps<T>, any>

TableProps的非可选部分:

export interface TableProps<T> {
    columnConfigs: TableColumnConfig<T>;
    tableStore: TableStore<T>;
}

TableStore只有一个必需属性:

export class TableStore<T> {
    public data: T[];
}

TableColumnConfigs并不是非常重要,因为T仅用于可选属性:

export interface TableColumnConfigs<T> {
    render?: (data: T) => JSX.Element
}

此&lt;表&gt;已经使用了几个地方,我正在添加一个功能:可选的分层数据,所以我们可以停止使用Kendo's TreeList(这是非常非常有用的,但在我们的环境中加载有点慢)。

我的问题:我想声明T,表中使用的数据类型,由类外的人提供,可能具有特定属性, type有递归子,但不是必需的。

我试过这个:

export interface ChildData<T> {
    children?: (T & ChildData<T>)[]
}
export class Table<T extends ChildData<T>> extends React.Component<TableProps<T>, any> ...

这不起作用,因为外部类没有定义名为“children”的属性。

问题在于TypeScript 2.8不喜欢它:当我实际在某处使用Table时,它会谴责T没有实现ChildData。 (我现在正在使用TS 2.3进行编译,但我会升级到2.4,在某些时候,很快就会发生,我发誓。最终。无论如何,我绝对不希望被阻止< / em>来自升级。我知道它在2.8上不起作用,因为我的IDE使用2.8运行Intellisense,但我正在运行2.3编译器。)

我也尝试使用union和intersection类型声明,但它们根本无法编译,即使在TS 2.3下:

export class Table<T & ChildData<T>> extends React.Component<TableProps<T>, any> ...
export class Table<T | ChildData<T>> extends React.Component<TableProps<T>, any> ...

有没有办法说“我有一个通用参数T,可以实现一个ChildData,但不是必须的?”我的&lt;表&gt;组件已经在其他地方的几个地方使用,并且它将由不是我的人使用。我不希望要求Table的使用者也通过他们没有使用的“children”属性来扩展他们的T类型(因为表的层次结构特征是完全可选的)。

1 个答案:

答案 0 :(得分:0)

在经历了一些困难之后,我终于意识到ChildData只在一个地方很重要:在&#34;数据&#34; TableStore的属性,它是所有相关数据的所在。所以我重新定义了TableStore:

export class TableStore<T> {
    public data: (T & ChildData<T>)[];
    constructor(input: T[]) { this.data = input; }
}

显然,你不能使用&amp;和|在通用参数中,但是&#34;扩展&#34;没关系。而且,如果你不断传递泛型参数,TypeScript最终会失去对泛型的精细细节的追踪。在类中使用T并在属性中使用(T&amp; somethingElse)的行为允许我直接将T分配给(T&amp; somethingElse)。

我假设,就像TypeScript 2.4收紧泛型一样,未来的TypeScript版本将禁止我目前正在逃避的诡计。

请注意,实施有点不稳定,因为我必须转向&lt; T&amp; ChildData&LT; T&GT;&GT;在&lt; Table&gt;内的几个地方,以及在消费类中我生成TableStore的数据。