typescript - 如何编写启用 no-unsafe-any 的类型保护?

标签 typescript tslint

我试图通过使用更严格的 lint 规则集来收紧我的 TS 代码,但我正在努力解决动态的合法用途。

我正在制作一个类型保护来检测某些东西是否是可迭代的(如果不是,将它包装在一个数组中),除了抑制 lint 规则来告诉 TS 是 kosher 之外,我不知道该告诉 TS 什么:

function isIterable(obj: any): obj is Iterable<unknown> {
    return obj && typeof obj[Symbol.iterator] === 'function';
}

我尝试将其更改为:
function isIterable(obj: undefined | {[Symbol.iterator]?: unknown}): obj is Iterable<unknown> {
    return !!obj && typeof obj[Symbol.iterator] === 'function';
}

不使用 any 编译,但它没有用,因为我想将未知类型的值传递给它。

是否有一种“干净”的方式说“是的,我实际上想依靠 JS 返回 undefined 来访问对象上不存在的属性”?特别是因为这是编写类型保护的重点。

最佳答案

我不知道像 no-unsafe-any 这样的东西在 user-defined type guard 的实现中是否会让你买太多东西,因为通常这种类型保护的全部目的是允许编译器缩小值,它通常无法通过内置控制流缩小来完成。我当然会理解在这样的实现中暂停 linter 规则。

但我认为你几乎可以得到你正在寻找的行为:

function isIterable(obj: unknown): obj is Iterable<unknown> {
  if ((typeof obj !== 'object') || (obj === null)) return false; 
  // obj is now type object
  const wObj: { [Symbol.iterator]?: unknown } = obj; // safely widen to wObj
  return typeof wObj[Symbol.iterator] === 'function'; 
}

这是要跳过的几个环节,但我们的想法是使用控制流缩小来缩小 unknownobject ,然后加宽 object专门针对具有您要检查的可选属性的类型(这是通过引入新变量来实现的)。最后,在加宽的类型上检查该属性的类型。由于您要检查的属性键是符号类型,因此您需要在加宽类型中提及特定的属性名称。如果属性键是字符串,则可以使用 string index signature 逃脱。 :
function isPromise(obj: unknown): obj is Promise<unknown> {
  if ((typeof obj !== 'object') || (obj === null)) return false;
  // obj is now type object
  const wObj: {[k: string]: unknown} = obj; // safely widen to wObj
  return typeof wObj.then === 'function';
}

无论如何,我希望这能让你更接近你的目标。祝你好运!

关于typescript - 如何编写启用 no-unsafe-any 的类型保护?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54611925/

相关文章:

javascript - 有什么方法可以使用拖放以 Angular 上传 .ply、.STL、.obj 文件吗?

typescript - 错误 : Cannot find module 'tslint/lib/lint' when trying to extend tslint-microsoft-contrib

typescript - 在 Typescript 中,什么是 !取消引用成员时的(感叹号/爆炸)运算符?

angular - 如何解决 "unexpected token : A constructor, method, accessor, or property was expected"错误?

javascript - 从下拉列表中选择时如何获取日期对象

javascript - 任意泛型的 typescript map

angular - angular指令选择器与tslint的冲突

angular - Angular 8错误-无法读取未定义的属性 'toString'

typescript - 如何忽略 "tslint:recomended"的分号

typescript - TsLint: '$http' 不能在构造函数中声明