Reputation: 5171
I have a function like this:
export const getValue = (
options: Options = { someMapping, someFunction }
): string | MyType => {
...
return someFunction({ ...someData });
};
Right now, the return type is string or MyType.
This is because someFunction can either return string or MyType.
Is there a way to use TypeScript conditional type to return the correct type based on what someFunction actually returns?
[Additional Info after first post]:
Here is the definition of Options type:
export interface Options {
someMapping: MappingType;
someFunc: (data: MyType) => MyType | string;
}
The someFunc param is a function that expects a MyType param.
Here are two actual functions I pass in depends on the situation:
const myFunc = (data: MyType): string => {
return data.someProperty;
};
const myFunc = (data: MyType): MyType => {
return data;
};
Upvotes: 0
Views: 1752
Reputation: 36045
I think the closest you can do is type someFunction
and use function overloading. The Options
makes it a little more complicated, but something like this should work:
type MyFunc<T extends MyType | string> = () => T;
interface Options<T extends MyType | string> {
someMapping: WhateverTypeThisIs;
someFunc: MyFunc<T>;
}
function getValue(options: Options<MyType>): MyType;
function getValue(options: Options<string>): string;
function getValue<T extends MyType | string>(options: Options<T>): T {
return options.someFunc();
}
So now you should get typings for something like this:
const myTypeOptions: Options<MyType> = {
someMapping: {},
someFunc: () => ({ myParam: "MyValue" })
};
const myStringOptions: Options<string> = {
someMapping: {},
someFunc: () => "Hello"
};
const myTypeValue = getValue(myOptions); // myNumberValue is of type { myParam: string };
const myStringValue = getValue(myStringOptions); // myStringValue is a string;
This is of course dependent on the fact that the function in question always returns a MyType
or always returns a string
. If it changes depending on the parameters of the function, then it will always be a MyType | string
because Typescript would not be able to determine that. It would be up the caller to figure out what it is.
EDIT:
Based on the scenario you presented, something like this might help. You can create to types of MyFunc
.
type MyTypeFunc = (myType: MyType) => MyType;
type MyStringFunc = (myType: MyType) => string;
interface MyOptions {
someMapping: WatheverTypeThisIs;
}
interface MyTypeOptions extends MyOptions {
someFunc: MyTypeFunc;
}
interface MyStringOptions extends MyOptions {
someFunc: MyStringFunc;
}
function getValue(options: MyTypeOptions): MyType;
function getValue(options: MyStringOptions): string;
function getValue(options: MyTypeOptions | MyStringOptions): T {
return options.someFunc();
}
Now, whenever you call it you can create or options like this:
const myTypeOptions: MyTypeOptions = {
someMapping: {},
someFunc: (myType) => myType
}
const myStringOptions: MyStringOptions = {
someMapping: {},
someFunc: (myType) => myType.someProperty
}
const myTypeValue = getValue(myTypeOptions); // myTypeValue will be of type MyType
const myStringValue = getValue(myStringOptions); // myStringValue will be of type string
Upvotes: 1
Reputation: 481
playground you can let typescript infer return type. Function overloading provided by @DeeV works as well.
Upvotes: 0