TypeScript defaultIfUndefined function typing

Viewed 51

I'm trying to write a simple function, which returns a defaultValue, if value === undefined.

The function is super simple:

const defaultIfUndefined = (value, defaultValue) => {
    return value === undefined ? defaultValue : value;
}

But the typings / type inference won't work.

The function should simply remove undefined from the types.

I tried several different things, but there's always some error.

1.

const defaultIfUndefined = <T>(value: T, defaultValue: Exclude<T, undefined>): Exclude<T, undefined> => {
    return value === undefined ? defaultValue : value;
}

2.

const defaultIfUndefined = <T, U extends Exclude<T, undefined>>(value: T, defaultValue: U): U => {
    return value === undefined ? defaultValue : value;
}

3.

const defaultIfUndefined = <T, U extends T | undefined>(value: U, defaultValue: Exclude<U, undefined>): Exclude<U, undefined> => {
    return value === undefined ? defaultValue : value;
}

4.

const defaultIfUndefined = <T, U extends T | undefined, V extends Exclude<U, undefined>>(value: U, defaultValue: V): V => {
    return value === undefined ? defaultValue : value;
}

The first example is working fine, as long as I return ... as any.

But is there some way to get this working without as any?

--

Link to TypeScript Playground

1 Answers

Conditional types that contain unresolved type parameter will genrally require a type assertion. This is due to the fact that typescript does not do much math on such types, it just checks for exact matches of the conditional type.

A solution would be to avoid conditional types:

const defaultIfUndefined = <T>(value: T | undefined | null, defaultValue: T & {}): T => {
  return value || defaultValue;
}

let a : string | null = Math.random() > 0.5 ? "" : null;
let aNotNull = defaultIfUndefined(a, "") // string 

Just a note on the T & {}. If you change it to just T, typescript will be too aggressive in inferring a literal type, the & {} fixed that.

Related