在TypeScript中,“asserts value is type”和“value is type”有什么区别?

6

TypeScript拥有is运算符,它可以帮助创建一个测试函数来进行类型检查。最近我看到两种不同的实现方式,其中一种使用了asserts关键字。

我没有在文档中找到这两种用法的区别信息。我稍微试了一下,如果我没记错的话,asserts不允许从函数中返回任何东西,但除此之外我没有发现任何区别。

以下是我测试过的代码:

// Asserts and tests the value without returninng anything
function assertIsString(value: unknown): asserts value is string {
  if (typeof value !== "string") throw Error("value is not a string");
}

// Tests the value and returns something so it can be used for typecheck
// more explicitly
function testIsString(value: unknown): value is string {
  return typeof value === "string";
}

const string = "hello";
const number = 123;

assertIsString(string); // does nothing
assertIsString(number); // throws Error
testIsString(string); // returns true
testIsString(number); // returns false

问题:这两种用例之间还有其他的差异吗?

1个回答

9
摘要:主要的区别在于一个是抛出,而另一个必须在条件下使用。
潜在引发异常并返回`void`的函数被称为断言函数
这些函数进行断言(你可以将其视为与编译器创建合约),即如果函数不引发异常,则返回值中的谓词将为真。从那时起(在当前范围内),谓词中的类型信息将生效。
返回布尔值的函数被称为类型谓词
与其可能抛出异常(并导致程序崩溃,除非捕获到异常-参见try...catch),这些函数只是简单地返回一个布尔值。如果布尔值为真,则在调用谓词的作用域的剩余部分(例如代码块)中,谓词将生效。
文档链接中针对每种情况都有几个示例(以及其他信息)。这是一个演示:

TS Playground

// predicate
function exists<T>(maybe: T): maybe is NonNullable<T> {
  return maybe != null;
}

// assertion
function assertExists<T>(maybe: T): asserts maybe is NonNullable<T> {
  if (maybe == null) throw new Error(`${maybe} doesn't exist`);
}

function example1() {
  console.log("example1 begin");
  let maybe: string | undefined;

  if (exists(maybe)) {
    maybe; // string
  } else {
    maybe; // undefined
  }

  console.log("example1 end");
}

function example2() {
  console.log("example2 begin");
  let maybe: string | undefined;

  assertExists(maybe);

  maybe; // string

  console.log("example2 end");
}

example1(); // 'example1 begin' then 'example1 end'
example2(); // only 'example2 begin', then exception is thrown: `undefined doesn't exist`


1
每天在SO上闲逛,真是惊奇,总能学到新东西。=) - Matthieu Riegler
2
@MatthieuRiegler 你应该在 TS 存储库的 issues 中逛逛!(该链接是按最多反应排序的视图)。 - jsejcksn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接