Reputation: 2872
Is it possible to return a different type if an optional key in an object is defined. In the following code I try to explain what I am trying to achieve:
interface Model {
name: string;
}
interface Arg {
id?: number;
}
const func = (obj: Arg): Arg["id"] extends number ? Model : Model[] => {
if (obj.id) {
return eval(""); // will return Model;
} else {
return eval(""); // will return Model[];
}
}
const all = func({}); // correct `Model[]` inference
const single = func({ id: 1 }); // expected inference `Model`, actually `Model[]`
Ignore the eval
call here, in my actual code this is actually a service that returns any
as well. What I'd like to have it back from this function is that everytime I pass an id
to the object as argument, it returns a single Model
otherwise Model[]
.
I expected the signature of my method to be correct
(obj: Arg): Arg["id"] extends number ? Model : Model[]
but that doesn't seem to be working, is there a way to get it back what I am expecting?
Upvotes: 0
Views: 173
Reputation: 153140
Arg["id"]
will always get you number | undefined
. You have to make the function generic:
const func = <T extends Arg>(obj: T): T["id"] extends number ? Model : Model[] => {
if (obj.id) {
return eval(""); // will return Model;
} else {
return eval(""); // will return Model[];
}
}
Now T
refers to the type of the actual argument and not the Arg
interface.
Upvotes: 1