Reputation: 2318
Please forgive me, I'm a javascript developer trying to learn typescript. In a challenge I've hit a snag.
So, I've got some interfaces and a tray of objects (data) and I'm trying to use the interface as a criteria in a filter function, but the type 'Cat' is not defined. I tried exporting it, but it brought other errors.
interfaces:
interface Cat {
type: 'cat';
name: string;
hunts?: string;
}
interface Fish {
type: 'fish'
name: string;
hides?: string;
}
export type Animal = Cat | Fish;
export const isCat = (animal: Animal): animal is Cat => animal.type === 'cat';
export const isFish = (animal: Animal): animal is Fish => animal.type === 'fish';
data:
import { Animal} from '../interface/species';
export const pets: Animal[] = [
{
type: 'cat',
name: 'Mr Whiskers',
hunts: 'mice'
},
{
type: 'fish',
name: 'bubbles',
hides: 'castle'
}
];
my trouble is with this filter function:
export function filterAnimal(animal: Animal[], criteria: Cat): Cat[] {
return animal.filter((pet) => {
for (var key in pet) {
if (pet[key] === criteria)
return pet;
}
});
}
How can I use Cat as the criteria?
Upvotes: 1
Views: 2114
Reputation: 2388
Types and interfaces are a part of typescript and they get removed during complication, so you cannot access them at runtime directly.
However, you can use a property which identifies you type. In your case, it looks like each Cat
has type === "cat"
, so in your filter you could do:
export function filterAnimal(animals: Animal[], type: "cat" | "dog"): Animal[] {
return animals.filter((animal) => animal.type === type);
}
If you'd like a function that specifically filters Cats
, you can do so similarly:
export function getOnlyCats(animals: Animal[]): Animal[] {
return animals.filter((animal) => animal.type === "cat");
}
Now, in some cases you may need to rely on the fact that your function only returns instances of the Cat
type. For example, you want to print what the cat hunts without errors. In this case, you'll need to manually assert that the function in fact returns an array of Cat
objects, by casting the return type.
function getOnlyCats(animals: Animal[]): Cat[] {
return (animals.filter((animal) => animal.type === "cat")) as Cat[];
}
// now you can safely do
const cats = getOnlyCats(animals);
cats.forEach(cat => {
if (cat.hunts) {
console.log(`cat ${cat.name} hunts ${cat.hunts}.`)
} else {
console.log(`cat ${cat.hunts} doesn't hunt.`)
}
});
Check out a live example here.
Upvotes: 1