我正在尝试创建列列表,其中每个列都有我想由类型系统强制执行的约束。列渲染器具有通用的value
属性,还具有valueGetter
,应返回自定义渲染器的适当类型。
我的困难在于,当我声明数组时,我不知道每种类型将是什么,因此我求助于unknown
,这使我对列的分配不强制类型。
export interface Grid<R> {
// How can I specify that the second type param should be inferred from its usage?
columns: GridColumn<R, unknown>[];
}
我的问题是:如何在value
界面中推断GridColumn
的类型
/**
* R is the type of the whole record for current row
* V is the type of `ColumnRenderer#value`
*/
export interface GridColumn<R, V> {
renderer: ColumnRendererSpec<R, V>;
}
/** The component that will be dynamically instantiated */
export interface ColumnRenderer<V> {
value: V;
}
interface ColumRendererConstructor<V> {
new(...args: any[]): ColumnRenderer<V>;
}
interface ValueGetter<R,V> {
(record: R): V
}
export interface ColumnRendererSpec<R, V> {
type: ColumRendererConstructor<V>;
/** Retrieves what is going to be passed to set ColumnRenderer#value */
valueGetter: ValueGetter<R, V>;
}
export interface Grid<R> {
columns: GridColumn<R, unknown>[];
}
这就是我想要的称呼
export interface Icon {
code: string;
label: string;
}
export interface Tooltip {
text: string;
tooltipText: string;
}
/** Type of record being passed to this grid */
interface MyRecord {
code: string;
label: string;
text: string;
description: string;
}
/** Renderers */
@Component({template: `<p><clr-icon icon="value.code"></clr-icon>value.label</p>`})
export class IconRenderer implements ColumnRenderer<Icon> {
value: Icon;
}
@Component({template: `<p [title]="value.tooltipText</p>value.text`})
export class TooltipRenderer implements ColumnRenderer<Tooltip> {
value: Tooltip;
}
const grid: Grid<MyRecord> = {
columns: [
{
renderer: {
type: IconRenderer,
// This is compiling but shouldn't because valueGetter should return an Icon //
valueGetter: (r) => 2,
},
},
{
renderer: {
type: TooltipRenderer,
// This doesn't compile, but I wish I didn't have to cast
valueGetter: (r) => 2,
},
} as ColumnRendererSpec<MyRecord, Tooltip>,
]
};
正如代码中的注释所表明的,我想强制执行valueGetter
返回从ColumnRendererSpec#type
的value属性推断出的正确类型
答案 0 :(得分:1)
可能不是最好的方法,但是由于列渲染器实现interface ColumnRenderer<V>
,并且由于V
应该是valueGetters
的返回类型,所以我们可以传递列渲染器的构造函数和{{1 }}方法作为实用程序方法的参数,该实用程序将创建渲染器spec对象,并有助于getter从传递给valueGetter
的泛型中推断其返回类型。
示例:
ColumnRenderer