我试图正确键入以下函数:
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编译器没有抱怨。
这是预期的行为还是我以不正确的方式使用未知?还有其他方法可以实现该函数的正确键入吗?
答案 0 :(得分:1)
您需要使用自己的条件类型来将Exclude
类型映射到null
,而不是使用undefined
。由于条件是在联合类型的每个成员上执行的,因此代码非常简单。唯一需要注意的是,如果您指定函数的返回类型是有条件的,则必须强制转换实际值:
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