Home > Back-end >  How to deal with TypeScript not treating uninitialized optional parameter as undefined
How to deal with TypeScript not treating uninitialized optional parameter as undefined

Time:07-18

Here's the simplified reproduction of my function:

const nullify = <T extends string | undefined>(
  value?: T,
): T extends string ? string : null => {
  if (value === undefined) return null as any;
  return value as any;
};

What I expect from these function typings is to treat lack of value as undefined, but TypeScript doesn't allow this, and instead it returns a union string | null. The only way to get null from this function is to explicitly pass undefined.

const result1 = nullify('string');  // result1 is string, as expected
const result2 = nullify(undefined); // result2 is null, as expected
const result3 = nullify();          // result3 is (string | null), but should be just null

Is there an idiomatic way to deal with this?

CodePudding user response:

The problem is that when you don't pass in a value argument, there is no value from which the compiler can infer T, and inference just fails. When inference fails, it generally falls back to its constraint, which in your case is string | undefined. If you want to change what it falls back to, you can set a generic parameter default using = syntax:

const nullify = <T extends string | undefined = undefined>( 
//                      default generic ----> ^^^^^^^^^^^
    value?: T,
): T extends string ? string : null => {
    if (value === undefined) return null as any;
    return value as any;
};

And you'll only see a difference when you leave value out:

const result1 = nullify('string');  // string, as expected
const result2 = nullify(undefined); // null, as expected
const result3 = nullify();  // null, as expected            
  • Related