【问题标题】:Using type predicates in class methods in TypeScript在 TypeScript 的类方法中使用类型谓词
【发布时间】:2021-07-07 16:20:42
【问题描述】:

我有一个这样定义的类

class Foo {
   value: string | null;
   constructor(){
      this.value = null;
   }
   private ensureValueExists():this.value is string{ //type predicate is not legal
      this.value = "bar";
      return true;
   }
   doStuffWithValue(){
      this.ensureValueExists();
      return 5 + this.value;  //ERROR, this.value can be null
   }
} 

我希望 ensureValueExists 方法能够告诉编译器 this.value 确实是一个字符串并且可以安全使用。 是否有特殊的语法可以使用,或者目前对于 TS 方法是否不可行?

【问题讨论】:

  • this.value ??= "bar";
  • 我希望我的类型谓词能够工作,所以我不必到处添加警卫。
  • 如果您可以确保value 稍后会被初始化,但在“真实代码”(非初始化代码)访问它之前仍然可用,那么您可以将其记为value!: string。如果你想要空安全访问,你可以说this.value ?? "fallback"。如果您想确保生成一个对象,其中value 被视为非空,您可以有一个单独的接口。在这里很难说哪个是正确的选择。
  • “我希望我的类型谓词起作用,所以我不必到处添加警卫。”但是你仍然需要在任何地方添加断言
  • 我不明白,使用 jcalz 的解决方案,它可以在没有非空断言的情况下工作。

标签: typescript types predicate


【解决方案1】:

您可以使用缩小thisassertion method。文档中并没有特别明确对此的支持,尽管与microsoft/TypeScript#32695 相关联的commit(PR 实现断言函数)表明这是可能的。

所以在你的情况下它看起来像:

  private ensureValueExists(): asserts this is { value: string } {
    this.value = "bar";
  }

(请注意,您不能在断言函数/方法中返回任何内容),然后以下工作:

  doStuffWithValue() {
    this.ensureValueExists();
    return 5 + this.value;  // okay
  }
}

肯定有caveats 与断言函数和方法相关联,但由于您只是在this 上进行操作,因此您不会在这里遇到它们。

Playground link to code

【讨论】:

  • 我不明白这怎么可能。不错的技巧。
【解决方案2】:

这种语法称为user-defined type guard。它可用于缩小其参数的类型,但除此之外没有任何作用。例如,即使这段代码也不起作用:

let value: unknown

function isValueString(): value is string { // Cannot find parameter 'value'.
    return typeof value === 'string'
}

Playground link

还有assertion function 语法,您可能一开始就打算使用它。但是,它具有与上述相同的限制,除了函数参数之外,您不能将其用于任何其他对象:

let value: unknown

function ensureValueIsString(): asserts value is string { // Cannot find parameter 'value'.
    value ??= 'bar'
}

Playground link

【讨论】:

  • 是的,我知道,我要问的是方法是否可行。
  • 我不这么认为。如何在构造函数中设置一个默认值并使value 不可为空?
  • 如果您缩小this(这是一个隐式参数),则可以使用方法;在上方或下方或任何地方查看我的答案
猜你喜欢
  • 2020-01-27
  • 2020-01-05
  • 2023-01-24
  • 1970-01-01
  • 2020-09-17
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
  • 2018-10-26
相关资源
最近更新 更多