Reputation: 1159
Starting with an Animal interface, and a map of animals in my farm:
export interface Animal {
type: string;
edible: boolean;
}
export interface Farmland{
[key: string]: Animal;
}
All works good. Here's my farm -
const farm: Farmland = {
bob: { type: 'sheep', edible: true },
daisy: { type: 'cow', edible: true }
}
Now my farn might have some smaller parts in it, and I want a new type which will contain either the animals or these parts:
export interface FarmlandOrAnimalMap {
[key: string]: Animal | Farmland;
}
const bigField: FarmlandOrAnimalMap = {
bob: { type: 'sheep', edible: true },
daisy: { type: 'cow', edible: true },
pasture: {
jack: { type: 'dog', edible: false }
},
pond: {
donald: { type: 'duck', edible: true }
},
farmhouse: {
hernietta: { type: 'monkey', edible: false }
}
};
That seems to work too - I can happily reference {{bigField.pond.donald.edible}}
(using e.g. angular) and all other expected object properties in my markup. Here's what I can't do though -
export class AnimalOven{
constructor() {
const donald = bigField.pond.donald;
}
}
The error is Property 'donald' does not exist on type 'Animal | Farmland'. Property 'donald' does not exist on type 'Animal'
. (This error will also be thrown by an angular compiler when I build the application.)
Typescript evidently knows bigField.pond
might be Farmland (with its string index) or an Animal so I'm not sure why it cannot infer the correct type here. In short:
Is there a way for Typescript to correctly infer type when using a type union of strong-type and {[key:index]: strong-type} ?
(Obviously there might be better ways of creating my farm and animals, use of keys, appropriate use of arrays; but the question here really relates to Typescript inference of map types)
Thanks.
Upvotes: 0
Views: 286
Reputation: 185280
By declaring it to be a FarmlandOrAnimalMap
you tell the compiler that the content of the variable is more generic than what it actually is here.
If you take away the type annotation of bigField
, this will work as the type of the entire object tree is derived.
For any variable of type FarmlandOrAnimalMap
the compiler can never infer whether a property is an Animal
or Farmland
unless you introduce additional checks.
Upvotes: 0