Reputation: 487
I'm sure this is possible in TypeScript, but the closest resource I could find is this SO question which doesn't seem to work for me.
I have a class that gets options passed in the constructor, and based on that one of its methods should change its return type from string
to string[]
:
(new MyClass({ multiple: true })).getData(); // returns string[]
(new MyClass({ multiple: false }).getData(); // returns string
What I've tried is to make the options generic and have a conditional return type in getData
:
type Options = {
multiple: boolean;
}
class MyClass<O extends Options> {
constructor(private options: O) {}
public getData = (): O["multiple"] extends true ? string[] : string => {
if (this.options.multiple) {
return ["foo", "bar"] as string[];
}
return "foo" as string;
};
}
But this gives the error TS2322: Type 'string[]' is not assignable to type 'O["multiple"] extends true ? string[] : string'.
.
Then I found the SO question linked above and thought that perhaps the "extraction" of O["multiple"]
is too complex for TS, so I extracted only the "multiple" field into a generic (instead of the whole options object):
class Day<TReturnsArray extends boolean> {
constructor(private options: { multiple: TReturnsArray }) {}
public getData = (): TReturnsArray extends true ? string[] : string => {
if (this.options.multiple) {
return ["foo", "bar"] as string[];
}
return "foo" as string;
};
}
But, alas, same error here. I'm not sure why string[]
isn't assignable the conditional return type, and the error message doesn't try to "drill down" like other error messages usually do.
Upvotes: 2
Views: 235
Reputation: 33061
You just need to overload your method:
type Options = {
multiple: boolean;
}
class MyClass<O extends Options> {
constructor(private options: O) { }
public getData(): O["multiple"] extends true ? string[] : string
public getData() {
if (this.options.multiple) {
return ["foo", "bar"];
}
return "foo" as string;
};
}
const stringArray = (new MyClass({ multiple: true })).getData(); // returns string[]
const string = (new MyClass({ multiple: false })).getData(); // returns string
COnditional type only works/sopported in overloaded signatures
Upvotes: 4