【问题标题】:Is it possible to detect unnecessary type guards?是否可以检测到不必要的类型保护?
【发布时间】:2020-01-16 11:32:59
【问题描述】:

我有以下打字稿代码:

type Nothing = undefined | null;
export const isNothing = <T>(val: T | Nothing): val is Nothing =>
  val === null || typeof val === 'undefined';

isNothing 是一种类型保护,主要检查是否设置了值。

我想在运行前检测以下内容:

const foo:number = 42;
if(isNothing(foo)) { /* ... */ }

这里的情况是类型保护是多余的。由于foo 是显式类型的,所以它不能是nullundefined

我一直在尝试通过以下方式找到答案:

  • 如果val 不是联合类型,则重载isNothing 以返回类型never
  • 一些 linter 规则会在接受联合的函数的参数不是联合时进行标记(这感觉像是一种大锤方法)。
  • 一些明确检测不必要的类型保护的 linter 规则

在这种情况下,“检测”可能是编译时错误或 linter 通知。重要的是,这将是一个运行前检测。

【问题讨论】:

  • “检测”的结果应该是什么?
  • @user2864740 真棒问题 - 我已经更新以澄清我的意思是“预运行时”,tslinttsc
  • overloading 到底是什么意思,所以类型保护返回 never?类型保护必须返回一个布尔值。对于第二个要点:也许您的意思是将交集类型作为参数,那么所有传递的类型都必须满足指定的约束。
  • @iY1NQ,所以,我四处寻找探索的途径。通过“重载”,我的意思是,如果函数传递了非联合类型,则签名将返回never,这将导致我的代码出错(这是我想要的)......我不'不要以为这条路会硕果累累
  • @iY1NQ 至于'也许你的意思是一个交叉口类型作为参数',我不确定你在开什么车......最终这是一个类型保护,所以它需要参加工会,对吧?

标签: typescript static-analysis


【解决方案1】:

正如我在上面的 cmets 中解释的那样,如果检查是多余的,则类型保护本身不会阻止代码编译的解决方案。我认为术语“类型联合”在这种特殊情况下是指一个非空且未定义的变量,因此isNothing 类型保护检查将是多余的。

一种解决方案是强制编译器在调用isNothing 类型保护之前检查变量是否“可能为空或未定义”:

type Nothing = undefined | null;

export const isNothing = <T>(val: T | Nothing): val is Nothing =>
  val === null || typeof val === 'undefined';


let a!: number;
let b!: number | undefined;
let c!: undefined;
let d!: null;

function assertMaybeNothing<T extends (Exclude<T, Exclude<T, undefined | null>> extends never ? never : any)>(arg1: T) {
  return true;
}

assertMaybeNothing(a); // error because is never undefined or null
assertMaybeNothing(b);
assertMaybeNothing(c);
assertMaybeNothing(d);

if (assertMaybeNothing(a) && isNothing(a)) {
  let x = a;// is never
} 

Playground Link

【讨论】:

    【解决方案2】:

    我最终选择了这个:

    type Nothing = undefined | null;
    
    export function isNothing<T>(val: NonNullable<T>): never
    export function isNothing<T>(val: T | Nothing): val is Nothing
    export function isNothing<T>(val: T) { return val === null || typeof val === 'undefined'; }
    

    然后,我在我的 TSLint 配置中将 strict-boolean-expressions 设置为 true

    因此,我的 linter 现在会捕获不包含 nullundefined 的显式类型的变量传递给此函数。

    【讨论】:

      猜你喜欢
      • 2022-08-18
      • 1970-01-01
      • 1970-01-01
      • 2018-06-05
      • 2021-05-27
      • 2022-01-01
      • 2014-05-10
      • 2021-08-31
      • 2018-01-03
      相关资源
      最近更新 更多