问题描述
我正在尝试创建一个列列表,其中每列都有我希望由类型系统强制执行的约束.列渲染器有一个通用的 value
属性,还有一个 valueGetter
应该为自定义渲染器返回适当的类型.
I'm trying to create a list of columns where each column has constraints that I would like enforced by the type system. A column renderer has a generic value
property and also has a valueGetter
that should return the appropriate type for the custom renderer.
我的困难在于,当我声明数组时,我不知道每种类型将是什么,所以我求助于 unknown
这使得我对列的分配不强制类型.
My difficulty is that when I declare the array, I don't know what each of the types is going to be so I'm resorting to unknown
which makes my assignment to columns not enforce types.
export interface Grid<R> {
// How can I specify that the second type param should be inferred from its usage?
columns: GridColumn<R, unknown>[];
}
我的问题是:如何在我的 GridColumn
界面中推断 value
的类型
My question is: how can I infer the type of value
in my GridColumn
interface
/**
* 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 属性推断出的正确类型
As my comments in the code indicate, I'd like to enforce that valueGetter
returns the correct type inferred from ColumnRendererSpec#type
's value property
推荐答案
可能不是最好的方法,但是,因为列渲染器实现了 interface ColumnRenderer<V>
并且因为 V
code> 应该是 valueGetters
的返回类型,我们可以将列渲染器构造函数和 valueGetter
方法作为参数传递给将创建渲染器规范对象的实用程序方法,这将有助于getter 从传递给 ColumnRenderer
的泛型推断其返回类型.
Might not be the best way but, since the column renderers implement interface ColumnRenderer<V>
and since V
should be return type of valueGetters
, We can pass the column renderer constructor and valueGetter
method as parameters to a utility method that would create the renderer spec object and that would help the getter to infer its return type from the generic passed to ColumnRenderer
.
示例:
function createColumnRendererSpec<R, V>(
ctor: ColumnRendererConstructor<V>,
valueGetter: (r: R) => V): ColumnRendererSpec<R, V> {
return {
type: ctor,
valueGetter
}
}
这篇关于在泛型数组中强制执行子类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!