未知的打字稿条件类型

Typecsript conditional type with unknown

我试图正确输入以下函数:

function nullToUndefined(p: null): undefined;
function nullToUndefined<T extends Exclude<unknown, null>>(p: T): T;
function nullToUndefined<T extends Exclude<unknown, null>>(p: null | T): T | undefined
{
    return p === null ? undefined : p; 
}

在某些情况下似乎工作正常:

const a = nullToUndefined(null); // undefined
const b = nullToUndefined(true); // true 
const c = nullToUndefined(10);   // 10

但是它不适用于以下代码

const d = nullToUndefined(1 as number | null);

变量 d 的类型是 number | null,但我想看看 number | undefined。问题似乎出在 T extends Exclude<unknown, null> - 因为 unknown 是所有类型的超类型,我希望 T 是除 null 之外的所有类型,但显然它不能像这样工作。

例如我可以做到

const e: Exclude<unknown, null> = null;

并且 TS 编译器不会报错。

这种行为是预料之中的,还是我使用 unknown 的方式不正确?有没有其他方法可以实现函数的正确输入?

您需要使用自己的条件类型将 null 类型映射到 undefined 类型,而不是使用 Exclude。由于条件是在联合类型的每个成员上执行的,因此代码非常简单。唯一需要注意的是,如果您指定 return 类型的函数是有条件的,则必须强制转换实际值:

type NullToUndefined<T> = T extends null ? undefined : T

function nullToUndefined<T>(p: T): NullToUndefined<T>
{
    return (p === null ? undefined : p) as NullToUndefined<T>; 
}

const d1 = nullToUndefined(null); // undefined
const d2 = nullToUndefined(1 as number | null); // number | undefined