在 TypeScript(TS)中,never
类型是一个特殊的类型,它表示的是那些永不存在的值的类型。这听起来可能有点抽象,但实际上它在一些场景中非常有用。以下是 never
类型在 TypeScript 中的一些妙用:
-
表示函数永远不会返回:
当你有一个函数,它因为某些原因(如抛出一个错误)而永远不会正常返回时,你可以将其返回类型设置为never
。这有助于 TypeScript 的类型检查器更好地推断代码中的其他部分。function error(message: string): never { throw new Error(message); }
注意,如果你试图将这个函数的结果赋值给一个变量或将其作为其他函数的返回值,TypeScript 会报错,因为它知道这个函数永远不会返回。
-
表示类型守卫的排他性:
类型守卫是 TypeScript 中的一个功能,它允许你在运行时检查一个值是否属于某个类型,并相应地缩小其类型。当你知道某个类型守卫能够覆盖所有可能的输入时,你可以将其返回类型设置为never
,以表示如果条件不满足,代码将永远不会到达那个点。function isNumber(x: any): x is number { return typeof x === 'number'; } function isString(x: any): x is string { return typeof x === 'string'; } function assertNever(x: never): never { throw new Error(`Unexpected object: ${x}`); } function classify(x: any) { if (isNumber(x)) { return 'number'; } else if (isString(x)) { return 'string'; } else { // 如果我们确信上面的条件已经覆盖了所有可能的输入, // 那么这里的代码永远不会执行,所以我们可以使用 never 类型。 return assertNever(x); } }
-
在递归函数中表示基本情况:
当使用递归函数时,你可能有一个基本情况,当达到该情况时,函数不再递归调用自身。在这种情况下,将基本情况的返回类型设置为never
可以帮助 TypeScript 确保所有可能的输入都被正确处理。function factorial(n: number): number { if (n <= 1) { return 1; // 这里不是 never,因为我们返回了一个数字 } else { return n * factorial(n - 1); // 递归调用 } } // 假设我们有一个永远不会达到的情况(只是为了示例) function unreachable(x: never): never { throw new Error('This should never happen'); } // 错误的示例,只是为了说明 function factorialWrong(n: number): number { if (n <= 0) { // 这里应该返回一个数字,但我们假设它永远不会发生 return unreachable(n); // 这里 n 实际上是 number,不是 never } else { return n * factorialWrong(n - 1); } }
注意,在实际情况中,上面的
factorialWrong
函数中的unreachable
调用是错误的,因为n
是number
类型而不是never
类型。这只是一个为了说明never
类型的用法而设计的假设示例。 -
在条件类型中排除类型:
在条件类型中,你可以使用never
来排除某些类型。这在构建复杂的类型系统时可能很有用。type BanType<T, E> = T extends E ? never : T// x可以时任何类型,但不能是T类型 const isNoType = <T>(x: BanType<T, string>) => {console.log(x) }
type NonNullable<T> = T extends null | undefined ? never : T; // 使用示例 type T1 = NonNullable<string | null>; // string type T2 = NonNullable<number | undefined>; // number type T3 = NonNullable<never>; // never
通过正确地使用 never
类型,你可以编写出更加健壮和易于理解的 TypeScript 代码。