Why is TypeScript not inferring the optional parameter in this function as undefined
when it's omitted from the call?
function fooFunc<T extends number | undefined>(param?: T){
let x: T extends undefined ? null : T
x = param ?? null as any
return x
}
The function works as expected if explicitly passed undefined
, but not if the argument is just omitted:
const fooResult1:number = fooFunc(3)
const fooResult2:null = fooFunc(undefined) // <-- this works
const fooResult3:null = fooFunc() // <-- this doesn't; it infers null | number, not null
This issue can be resolved by widening the constraint to include unknown
, i.e.,
<T extends number | undefined | unknown>
. However, using unknown
may lead to other problems later on.
What could be causing this behavior and is there a workaround for it?
Update
Based on research, it seems that missing type parameters are inferred as unknown in TypeScript. See this SO answer by @jcalz. So the question now is whether there is a way around this issue or if debugging with unknown
is inevitable.
Update 2(revised)
I have encountered an issue with using unknown
--while changing the function signature to
function fooFunc<T extends number | undefined | unknown>(param?: T){
let x: T extends undefined ? null : T
x = param ?? null as any
return x
}
makes the function work correctly when called without a parameter (fooFunc()
), it also allows arbitrary parameters like fooFunc("hello")
, which is undesired behavior.
The same issue arises even if the generic is embedded within an object, as shown below:
function bazFunc<T extends number | undefined | unknown>(param: {a: number; b?: T}){
let x: T extends undefined ? null : T
x = param.b ?? null as any
return x
}
bazFunc({a:1, b:"hello"}) // <-- Undesired behavior