TS中never类型的妙用

        在 TypeScript(TS)中,never 类型是一个特殊的类型,它表示的是那些永不存在的值的类型。这听起来可能有点抽象,但实际上它在一些场景中非常有用。以下是 never 类型在 TypeScript 中的一些妙用:

  1. 表示函数永远不会返回
    当你有一个函数,它因为某些原因(如抛出一个错误)而永远不会正常返回时,你可以将其返回类型设置为 never。这有助于 TypeScript 的类型检查器更好地推断代码中的其他部分。

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

    注意,如果你试图将这个函数的结果赋值给一个变量或将其作为其他函数的返回值,TypeScript 会报错,因为它知道这个函数永远不会返回。

  2. 表示类型守卫的排他性
    类型守卫是 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);  
      }  
    }
  3. 在递归函数中表示基本情况
    当使用递归函数时,你可能有一个基本情况,当达到该情况时,函数不再递归调用自身。在这种情况下,将基本情况的返回类型设置为 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 类型的用法而设计的假设示例。

  4. 在条件类型中排除类型
    在条件类型中,你可以使用 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 代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值