未知的打字稿条件类型
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
我试图正确输入以下函数:
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