I have a data source, let's call it getData(), that returns objects. Sometimes it returns objects of known type (e.g. Person, Animal), but sometimes the returned object has an unknown shape.
(Link to TypeScript Playground)
type Person = { name: string; age: number };
type Animal = { species: string };
/**
* This interface stores all known object types returned by `getData()`.
* I'm storing it as an interface instead of `Person | Animal` because I
* need to store the "code" of a known type (e.g. `"person"` for `Person` type).
*/
interface DataCategory {
person: Person;
animal: Animal;
}
/** Our data source */
const getData: Person | Animal | any = () => {
return {}; // Mocked value
};
Now I wish to write a helper function useData() to narrow down getData()'s return value. It accepts an optional parameter of type keyof DataCategory and returns the corresponding type. I wish to make this function return any if we don't pass a parameter.
const person = useData("person"); // const person: Person
const animal = useData("animal"); // const animal: Animal
const notKnown = useData(); // const notKnown: any
I've tried the following implementation:
function useData<T extends keyof DataCategory>(category?: T) {
const data: any = getData();
return data as T extends undefined ? any : DataCategory[T];
}
const animal = useData("animal");
// ^ const animal: Animal
const notKnown = useData();
// ^ const notKnown: Person | Animal
// However, I want the above to be `const notKnown: any`
That doesn't work because useData() returned Person | Animal instead of any. How can I fix this problem?