For this scenario, it is recommended to utilize function overloads:
type FalsyValues = '' | null | undefined | 0 | false // no NaN
function func(): 's'
function func(arg: FalsyValues): 's'
function func(arg: unknown): 10
function func<T>(arg?: T | undefined): "s" | 10
function func<T,>(arg?: T) {
if (arg) return 's'
else return 10
}
let f = func() // 's'
let ff = func(0) // 's'
let fff = func(1) // 10
Playground
UPDATE
type FalsyValues = '' | null | undefined | 0 | false // no NaN
type Conditional<T> = T extends FalsyValues ? T extends unknown ? unknown extends T ? never : 's' : never : 10
function func<T extends string | null | undefined | number | boolean | object>(arg?: T): Conditional<T> {
if (arg) {
return 's' as Conditional<T>
}
else return 10 as Conditional<T>
}
let f = func('') // 's'
let ff = func(0) // 's'
let fff = func(1) // 10
let ffff = func() // 's' | 10
The primary issue arises with a function lacking an argument.
Since the argument type was not specified, I assumed it could be any value.
Therefore, I have defined the FalsyValues
type in case an argument is provided to the function.
UPDATE
I have included additional constraints:
type FalsyValues = '' | null | undefined | 0 | false // no NaN
type Conditional<T> = T extends FalsyValues ? 's' : 10
function func<T extends string | null | undefined | number | boolean | object = null>(arg?: T): Conditional<T> {
if (arg) {
return 's' as Conditional<T>
}
else return 10 as Conditional<T>
}
let f = func('') // 's'
let ff = func(0) // 's'
let fff = func(1) // 10
let ffff = func() // 's'
Playground