阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > never类型与void类型

never类型与void类型

作者:陈川 阅读数:15153人阅读 分类: TypeScript

在TypeScript中,nevervoid是两种特殊的类型,它们用于表示函数的返回值,但语义和用途截然不同。void表示函数没有返回值,而never表示函数永远不会正常返回。理解它们的区别对于编写类型安全的代码至关重要。

void类型的基本概念

void类型表示函数没有返回值。当函数执行完毕后,不会返回任何值(或者更准确地说,返回undefined)。这是JavaScript中默认的函数行为,TypeScript通过void类型显式标注这一点。例如:

function logMessage(message: string): void {
  console.log(message);
}

这里,logMessage函数没有return语句,因此它的返回类型是void。如果尝试显式返回一个值,TypeScript会报错:

function invalidVoidExample(): void {
  return "This will cause an error"; // Error: Type 'string' is not assignable to type 'void'
}

voidundefined的关系

在TypeScript中,voidundefined看似相似,但有细微差别。void表示“没有返回值”,而undefined是一个具体的值。如果函数显式返回undefined,它的类型可以是voidundefined

function returnsUndefined(): undefined {
  return undefined; // 合法
}

function alsoReturnsUndefined(): void {
  return undefined; // 也合法,因为void允许返回undefined
}

但反过来不行:

function invalidUndefinedExample(): undefined {
  // Error: A function whose declared type is neither 'void' nor 'any' must return a value
}

never类型的基本概念

never类型表示函数永远不会正常返回。它通常用于以下场景:

  1. 函数总是抛出异常。
  2. 函数包含无限循环。
  3. 类型收窄后不可能存在的分支。

抛出异常的函数

如果一个函数总是抛出错误,它永远不会有机会返回值,因此返回类型是never

function throwError(message: string): never {
  throw new Error(message);
}

无限循环的函数

类似地,如果一个函数包含无限循环,它的返回类型也是never

function infiniteLoop(): never {
  while (true) {
    // 无限执行
  }
}

类型收窄中的never

在类型守卫或条件类型中,never可以表示不可能存在的分支。例如:

type NonString<T> = T extends string ? never : T;

function filterStrings<T>(value: T): NonString<T> {
  if (typeof value === "string") {
    throw new Error("Strings are not allowed");
  }
  return value; // 类型为NonString<T>
}

voidnever的关键区别

  1. 语义差异

    • void:函数正常执行完毕,但没有返回值。
    • never:函数无法正常执行完毕。
  2. 可赋值性

    • void可以被赋值为undefinednull(在strictNullChecks关闭时)。
    • never是所有类型的子类型,可以赋值给任何类型,但没有任何类型可以赋值给never(除了never本身)。
let v: void = undefined; // 合法
let n: never = throwError("error"); // 只有通过never函数赋值

// 以下代码会报错
let invalidNever: never = 42; // Error: Type 'number' is not assignable to type 'never'
  1. 在联合类型中的行为
    • void在联合类型中会被保留。
    • never在联合类型中会被忽略,因为它表示“不可能存在”。
type UnionWithVoid = string | void; // string | void
type UnionWithNever = string | never; // string

实际应用场景

void的典型用法

  1. 事件处理函数
    许多事件处理函数没有返回值,适合用void标注:
button.addEventListener("click", (): void => {
  console.log("Button clicked");
});
  1. React组件中的副作用
    在React中,如果组件方法仅用于副作用操作,可以声明为void
class MyComponent extends React.Component {
  handleClick(): void {
    this.setState({ clicked: true });
  }
}

never的典型用法

  1. 全面性检查
    switchif-else链中,never可以确保所有可能的情况都被处理:
type Shape = "circle" | "square" | "triangle";

function getArea(shape: Shape): number {
  switch (shape) {
    case "circle":
      return Math.PI * 2;
    case "square":
      return 4;
    case "triangle":
      return 3;
    default:
      const exhaustiveCheck: never = shape; // 如果Shape有新增类型,这里会报错
      throw new Error(`Unknown shape: ${exhaustiveCheck}`);
  }
}
  1. 高阶类型工具
    在条件类型中,never常用于过滤或组合类型:
type ExtractStrings<T> = T extends string ? T : never;

type Result = ExtractStrings<"a" | 1 | true>; // "a"

常见误区与陷阱

  1. 混淆voidundefined
    虽然void允许返回undefined,但它们是不同的概念。void是一种类型标注,而undefined是一个值。

  2. 误用never作为变量类型
    声明一个never类型的变量通常没有意义,因为无法为它赋值(除了通过never函数):

let x: never; // 无法赋值
x = 42; // Error
  1. 忽略never在类型收窄中的作用
    在复杂类型逻辑中,未合理使用never可能导致类型安全性漏洞。例如:
function badTypeGuard(value: string | number) {
  if (typeof value === "string") {
    return value.toUpperCase();
  }
  if (typeof value === "number") {
    return value.toFixed(2);
  }
  // 这里value的类型是never,但如果没有处理,可能隐藏bug
}

高级类型系统中的交互

void在泛型中的行为

void作为泛型参数时,它会被视为普通类型:

type Wrapper<T> = { value: T };
const wrappedVoid: Wrapper<void> = { value: undefined }; // 合法

never与条件类型

在条件类型中,never会触发分布式行为:

type Distributed<T> = T extends any ? T[] : never;
type Result = Distributed<"a" | never>; // "a"[]

函数类型兼容性

void返回值类型在函数兼容性中有特殊规则。当一个函数类型声明为void时,实际实现可以返回任何值(但这些值会被忽略):

type VoidFunc = () => void;
const fn: VoidFunc = () => "hello"; // 不会报错,但返回值会被忽略

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌