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