Reputation: 318
I hope you can help me with TypeScipt ;)
Question:
How can I get a type from the object property that I receive from arguments?
Code:
const someVariable = 'test=123&test2=456';
// I want by default return type { [key: string]: any }[],
// but if options.parse === false { [key: string]: string }[]
function someFunction(options: string | IOptions) {
if (typeof options === 'string') {
return someVariable.split('&').map((part) => {
const [key, value] = part.split('=');
return { [key]: JSON.parse(value) };
});
}
return someVariable.split('&').map((part) => {
const [key, value] = part.split('=');
if (options.parse) {
return { [key]: JSON.parse(value) };
}
return { [key]: value };
});
}
someFunction()
// => { [key: string]: any }[]
someFunction({ parse: false })
// => { [key: string]: string }[]
Thank you for your help!
Upvotes: 0
Views: 553
Reputation: 329523
One way to do this is to make someFunction()
an overloaded function with multiple call signatures corresponding to the different input-output relationships you want to see:
// call signatures
function someFunction(options: IOptions & { parse: false }): Array<{ [k: string]: string }>;
function someFunction(options: string | IOptions): Array<{ [k: string]: any }>;
// implementation
function someFunction(options: string | IOptions): Array<{ [k: string]: any }> {
// impl unchanged
}
And you can see when you call it that it works as expected:
const valAny = Object.values(someFunction("aString")[0])[0]
// const valAny: any
const valString = Object.values(someFunction({ parse: false })[0])[0]
// const valString: string
You can also achieve this result with a generic function that returns a conditional type:
function someFunction<T extends string | IOptions>(
_options: T
): Array<{ [k: string]: T extends { parse: false } ? string : any }> {
const options: string | IOptions = _options;
// impl unchanged after this
}
And it behaves the same way for the calls we tested above:
const valAny = Object.values(someFunction("aString")[0])[0]
// const valAny: any
const valString = Object.values(someFunction({ parse: false })[0])[0]
// const valString: string
Each solution has its benefits and drawbacks, depending on the use case. Neither solution guarantees type safety inside the implementation of the function, so you need to be careful that the implementation really does conform to the call signatures you are using.
Upvotes: 2