I have a type as follows, where if name is anything OTHER THAN "filter" the type is "AggrEntry" and "filter" is of type "Aggr".
export interface Aggr {
[name: string]: AggrEntry;
filter?: Aggr;
}
However the ts code won't compile unless I change [name: string]: AggrEntry;
to [name: string]: any;
.
The error is
[ts] Property 'filter' of type 'ResponseAggregation' is not assignable to string index type 'ResponseAggregationEntry'.
Logically I am guessing typescript tries to assign [name: string]
to filter since filter itself can get mapped to [name: string]
. So how would I structure my interface so that the ts compiler knows that "name" won't ever be "filter" then.
If you define an indexer all properties must conform to the return type of the interface. You could do the following:
export interface Aggr {
[name: string]: AggrEntry |Aggr;
filter?: Aggr;
}
This is obviously not ideal as this allows other fields except filter
to be of type Aggr
.
Another option is to use a type
definition instead of an interface, and use a intersection 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
While we can access object fields as expected, creating an object of this type is a bit trickier. Creating an object literal with the filter
field will yield a similar error to your original. We can use Object.assign to create an instance of the type using object literals:
let test : Aggr = Object.assign({
foo: new AggrEntry()
}, {
filter: {
bar: new AggrEntry()
}
});
Or we can create a dedicated function to help with creation, that uses 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()
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With