typescript接口动态参数不会没有任何编译

时间:2018-04-03 12:46:11

标签: typescript

我有一个类型如下,如果名称是除了"过滤器"类型是" 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"永远不会过滤"过滤"然后

1 个答案:

答案 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()
    }
});