Let's pretend I have a function. It's a very nice function, very friendly. And it takes an argument, let's call it type
. But guess what? It's actually a string! Here, let me give you an example:
function returnWithType(o: any, type: 'string' | 'number') {
if (typeof o === type) return o
throw new Error(`AHHHH!!!!!`)
}
See what I did there? I checked the type against the type!
But, okay now let me ask you this... how can I specify the function's actual return type, so that if they pass "string"
then the return type is string
, and the same for number, but with "number"
instead of "string"
assuming they passed the string value "number"
into the second parameter in this case???
I basically want this:
function returnWithType(o: any, type: 'string' | 'number'):
asserts typeof o === as // <---- THIS
{
// ...
}
Or maybe this:
function returnWithType(...):
type extends 'string' ? string :
type extends 'number' ? number :
boolean
{
// ... solves world hunger ...
}
I just realized I can do this by creating the generic T extends ...
and returning a ternery based on T, but is there any cleaner way, maybe with some clever builtins, to derive this information automatically???
To avoid many conditional types you could use a map type:
type Types = {
string: string,
number: number
}
function returnWithType<K extends keyof Types>(o: any, type: K): Types[K] {
if (typeof o === type) return o
throw new Error(`AHHHH!!!!!`)
}
const str = returnWithType('string', 'string'); // string
const num = returnWithType(2, 'number'); // number