The need
The code is simple but my use case is complex:
type MyFn = <B extends ['A']>(
param?: B
) => B extends undefined ? 'TYPE_1' : 'TYPE_2'
// so that
const test1 = myFn() // shall be type TYPE_1
const test2 = myFn(['A']) // shall be type TYPE_2
- I would like that if
param
is undefined, then the type is'TYPE_1'
else it is'TYPE_2'
param
shall be dynamically typed, the goal is that the IDE autocompletes/validates values when writing the values inside the array- the type of
param
inside the function shall be at least (string[] | undefined)
What I have tried
I tried a lot of different configurations without success: typescript playground
The closest I could get actually was with this code:
type MyFn = <
T,
B extends ['A']
>(
param?: T | B
) => T extends string[] ? 'TYPE_2' : 'TYPE_1'
var a: MyFn3 = (param?) => (param ? 'TYPE_1' : 'TYPE_2') as any
const test1 = a() // IS type TYPE_1
const test2 = a(['A']) // IS be type TYPE_2
But the problem is that the inferred type inside of the function is any
because T
has no constraint type. But at the moment we constraint the T
type, the condition in the return type returns always true.
Is there any solutions to get around that problem ?
Real world use case
The main goal behind such a type is to define an array of string as props address of an object, and return the value at that address.
Eg: ['level1', 'level2']
would return myObject.level1.level2
Here is a simplified version of this real world use case
CodePudding user response:
Your B
type is never undefined
, because ['A']
is never undefined. The compiler can effectively simplify your expression:
type MyFn = <B extends ['A']>(
param?: B
) => B extends undefined ? 'TYPE_1' : 'TYPE_2'
to
type MyFn = <B extends ['A']>(
param?: B
) => false ? 'TYPE_1' : 'TYPE_2'
to
type MyFn = <B extends ['A']>(
param?: B
) => 'TYPE_2'
The fact that param
is optionally B
has no effect on B
itself.
You need to broaden B
:
type MyFn = <B extends ['A'] | undefined>(
which produces the correct result for
const test1 = myFn(undefined) // TYPE_1
and then default to make it work when omitted:
type MyFn = <B extends ['A'] | undefined = undefined>(
which produces the correct result for
const test1 = myFn() // TYPE_1