我有一个类型如下,如果名称是除了"过滤器"类型是" AggrEntry"和"过滤"属于" Aggr"。
export interface Aggr {
[name: string]: AggrEntry;
filter?: Aggr;
}
然而,除非我将[name: string]: AggrEntry;
更改为[name: string]: any;
,否则ts代码不会编译。
错误是
[ts] Property 'filter' of type 'ResponseAggregation' is not assignable to string index type 'ResponseAggregationEntry'.
逻辑上我猜测打字稿会尝试将[name: string]
分配给过滤器,因为过滤器本身可以映射到[name: string]
。那么我将如何构建我的接口,以便ts编译器知道" name"永远不会过滤"过滤"然后
答案 0 :(得分:5)
如果定义索引器,则所有属性都必须符合接口的返回类型。您可以执行以下操作:
export interface Aggr {
[name: string]: AggrEntry |Aggr;
filter?: Aggr;
}
这显然不太理想,因为这允许除filter
之外的其他字段属于Aggr
类型。
另一种选择是使用type
定义而不是接口,并使用交集类型:
export type Aggr = {
[name: string]: AggrEntry;
} & {
filter?: Aggr;
}
let test : Aggr;
let foo = test.foo // foo is AggrEntry
test.filter // works, is of type Aggr
虽然我们可以按预期访问对象字段,但创建这种类型的对象有点棘手。使用filter
字段创建对象文字将产生与原始字体类似的错误。我们可以使用Object.assign使用对象文字创建该类型的实例:
let test : Aggr = Object.assign({
foo: new AggrEntry()
}, {
filter: {
bar: new AggrEntry()
}
});
或者我们可以创建一个专用函数来帮助创建,使用Object.assign
:
function createAggr(dynamicPart: {
[name: string]: AggrEntry;
}, staticPart?: {
filter?: Aggr;
}) {
return Object.assign(dynamicPart, staticPart);
}
let test : Aggr = createAggr({
foo: new AggrEntry()
}, {
filter: {
bar: new AggrEntry()
}
});