Basically, I have an array of two types of animal: Cat
and Dog
. I would like to be able to access the properties of the cat when I know it's a Cat
, and access the properties of dog when I know it's a Dog
; however, I'm getting an error when trying to read woof
even after I checked the animal's type in the if
statement.
On a similar note, I'd love to have an error if I try to add the wrong properties to an element in the array, e.g. { type: 'dog', actions: { purr: true } }
(dogs don't purr).
How do I type-safely access the properties of an array element after narrowing on another property?
I'm not really tied to any of the code here, it was just my attempt at solving this problem. I'm getting the array of animals from the server, so I can't really change the actual data.
I'm happy to add any clarification if my question isn't clear.
interface DogActions { woof: true }
interface CatActions { purr: true }
type AnimalActions<T extends AnimalTypes> = T extends 'dog' ? DogActions : CatActions
interface Animal<T extends AnimalTypes> {
type: AnimalTypes
actions: AnimalActions<T>
}
type AnimalTypes = 'dog' | 'cat'
const arr: Animal<AnimalTypes>[] = [{ type: 'dog', actions: { woof: true }}, { type: 'cat', actions: { purr: true }}]
arr.forEach(animal => {
if (animal.type === 'dog') {
console.log(animal.actions.woof)
} else if (animal.type === 'cat') {
console.log(animal.actions.purr)
}
})
CodePudding user response:
I would recommend for more questions start putting your code into TypeScript Playground and attach a link to your question. How about this?
interface DogActions { woof: true }
interface CatActions { purr: true }
type Animal = { type: 'dog', actions: DogActions } | { type: 'cat', actions: CatActions }
const arr: Animal[] = [{ type: 'dog', actions: { woof: true }}, { type: 'cat', actions: { purr: true }}]
arr.forEach(animal => {
if (animal.type === 'dog') {
console.log(animal.actions.woof)
} else if (animal.type === 'cat') {
console.log(animal.actions.purr)
}
});
See it here working.