在单元测试中断言流类型错误

Asserting a Flow type error in unit tests

我们在 JavaScript 中使用 Flow 进行静态类型检查。 Flow 类型可能会变得复杂,我们曾遇到过问题,我们认为我们有很好的静态类型保护来防止格式错误的对象,但 Flow 注释问题意味着类型检查实际上并没有发现问题。

为了防止这个问题,我想编写基于类型的 "unit tests",它可以静态断言我们关于类型保护的假设。如果我想使用 type assertions:

断言 "valid" 案例,这很容易
type User = {|
    name: string
|};

const user = {name: "Bob"};
(user: User);

如果 user 是有效的 User,这将通过,如果不是,则类型检查失败。

但是,为了断言类型检查为我们提供的实际保护,我需要能够断言 Flow errors。例如,假设我想确保这无效:

const user = {name: "Bob", age: 40};

我可以通过

测试
// $ExpectError
const user = {name: "Bob", age: 40};

但我不能让它失败

// $ExpectError
const user = {name: "Bob"};

显然这个例子很简单,但是更复杂的类型(例如泛型)可以从这种类型的测试中受益。

我考虑过的选项:

有什么方法可以静态断言 Flow 断言应该失败,如果没有失败则抛出错误?

要断言单元测试中的某些代码行应该引发 Flow 错误,只需在这些行上方写一个 Flow 错误抑制注释,然后 运行 flow check --max-warnings 0 在整个单元测试文件夹中(或您的整个代码库)并断言该命令的退出状态为 0(无错误或警告)。您不需要单独 运行 每个单元测试文件上的命令。

正如 documentation for suppress_comment 所说,如果您在实际上不会触发 Flow 错误的行上方写 // $FlowExpectError 等抑制注释,Flow 将发出警告。

假设您将 suppress_comment 定义为将 $FlowExpectError 理解为抑制注释,这就是您的单元测试的样子:

// this type definition could be imported from another file
type User = {|
    name: string
|};

// Check that Flow doesn’t raise an error for correct usages
const user = {name: "Bob"};

// Check that Flow does raise an error for incorrect usages
// $FlowExpectError
const user = {name: "Bob", age: 40};

如果您 运行 flow check --max-warnings 0 在包含此文件的文件夹上并且命令成功退出,则您的 User 类型测试通过。