【问题标题】:TSNode + Mocha: Ignore TypeScript errors (make compiler emit on errors and make TSNode execute emitted code)TS Node + Mocha:忽略 TypeScript 错误(使编译器发出错误并让 TS Node 执行发出的代码)
【发布时间】:2020-05-06 16:51:39
【问题描述】:

在下面的代码中,虽然test2函数无效,但不影响test1函数的测试:

export function test1(): boolean {
  return true;
}

export function test2(): number {
  return "1";
}

测试:

import { assert as Assert } from "chai";
import { test1 } from "./example";


describe("Example", (): void => {
  it("Example", (): void => {
    Assert.isTrue(test1());
  });
});

但是 TSNode 执行的 Mocha 会失败:

TSError: ⨯ Unable to compile TypeScript:
Source/ProjectBuilder/example.ts(6,3): error TS2322: Type '"1"' is not assignable to type 'number'.

可以强制 TSNode 完成上述测试吗? TypeScript 有选项noEmitOnError...

我的 mocharc.yaml:

extension:
  - ts
spec: "**/*.test.ts"
require:
  - ts-node/register
  - tsconfig-paths/register

为什么我需要它

根据Clean Architecture,“业务规则不能依赖于任何东西,它必须是可测试的”。但是即使业务规则不依赖于视图、控制器等,如果视图、控制器等存在一些错误,我们也无法对其进行测试。

当我在我的应用程序中修改业务逻辑时,所有依赖它的东西都变得无效。假设在我的实体中,业务逻辑 type User { name: string; age: number } 已更改为类型 User { fullName: string; age: string; }。所有依赖于业务逻辑(视图、控制器、演示者等)的东西都变得无效 - 我也需要根据业务逻辑的更新来更正它。

// In business rules:

type User = { 
  ID: number;
  fullName: string; 
  age: string; // in past - number
}

// In controller:

class UserProfileController {
  // ...
  // All what comes from input field is string    ↓
  private onClickChangeUserAge(inputtedUserAge: string) {
    // This expression obeys to previous version of business rules!
    this.targetUser.age = Number(inputtedUserAge);
    // TypeScript will emit type error, when I try to test business rules,
    // however business rules does not depend on controller.
  }
}

但是,在大型应用程序中,这种更正可能需要几天、几周和几个月的时间。我们如何获得反馈证明至少业务逻辑工作正常并且我们的方式是正确的?

【问题讨论】:

  • 您将 编译时间运行时间 混淆了。该代码与任何静态类型语言中的程序一样,如果不编译将不会运行:它不是有效的 Typescript 程序。同样,“@#$^%*^%arstlh”不是有效的 Typescript 程序。
  • @JaredSmith,感谢您的评论。我知道 Webpack 可以编译 TypeScirpt(当然,使用 ts-loader),即使 TypeScript 中有错误。如果是调用undefined 的属性之类的错误,JavaScript 将一直执行到该命令为止。 TSNode 也可以做同样的事情吗?
  • 你为什么要手动测试编译器为你检查的东西?如果您只是想尝试颠覆它,为什么还要打扰 Typescript?这一切有什么意义?您实际上想在这里完成什么?
  • @JaredSmith,好吧,我会解释的。当我在我的应用程序中修改业务逻辑时,所有依赖它的东西都变得无效。理想情况下,我需要在运行测试之前解决应用程序中的所有错误,但这可能需要很长时间。取而代之的是,首先我只需要测试修改后的业务逻辑。但由于上述问题,我无法运行 Mocha。
  • 我还是不明白。同样,编译器将进行类型检查。您字面意思(正如您所发现的)不能将错误的类型传递给函数或从中返回错误的类型,代码甚至无法编译,更不用说运行了。所以你真的不能犯这样的错误,这样的测试是没有意义的,你不需要它们。这是使用静态类型系统的全部要点。因此,要么用 Javascript 编写代码并进行适当的 Javascript 测试,要么用 Typescript 编写代码并进行适当的 Typescript 测试。如果您再次更改逻辑,您的应用将无法编译。

标签: node.js typescript mocha.js ts-node


【解决方案1】:

让 Typescript 忽略类型是没有意义的。您所描述的类似于要求一个确认 2 + 2 = 5 的计算器,只是暂时的,因为最终您会要求 2 + 3 = 5,但这可能需要很长时间。

您问题中的假设是numberstring 足够兼容,无论test2 返回1 还是"1",您的业务逻辑都将是合理的。这不是真的:例如,1 + 1 == 2"1" + 1 == "11""1" - 1 == 0。根据哪些适用于您的案例,忽略类型可能允许您测试业务逻辑,或者可能让您对损坏的系统产生错误的信心。我敢冒险,一般来说,数据类型算作您要验证的业务逻辑的一部分——如果不是业务逻辑,数据模型会算作什么?

相反,您所描述的是逐步迁移,在此期间业务规则确保test2 返回string | number。通过在类型系统中准确描述迁移,您可以确认业务逻辑是否正确应用——如果在整个迁移过程中都是如此——并且还可以提供一个只能应用的类型来自某些模块和调用站点,这些模块和调用站点可以在您完成迁移时收紧。

【讨论】:

  • 感谢您的回答。 “你要求 Typescript 忽略类型是没有意义的。” - 我向 TSNode 询问的只是构建 JavaScript 并在存在类型错误时执行事件。为什么我对 TSNode 的要求对于带有 TSLoader 的 Webpack 是可能的?即使存在 TypeErrors,Webpack 也会使用 noEmitOnErrors: false 构建脚本。另外,很抱歉,test1test2 的示例与实际应用相距甚远:我假设test1 是业务逻辑的一部分,而test2 是例如控制器的一部分。我将添加新示例。
  • 我认为你的回答是“现在不可能”。
  • @GurebuBokofu 如果这就是我的意思,我会写的。我写的是“这对你没有意义”,我坚持作为总结。
【解决方案2】:
type User = { 
  ID: number;
  fullName: string; 
  age: string | number
}

您可以指定这两种类型以使迁移更容易,而不是到处使用//@ts-ignore

这将在各处添加适当的建议,例如:

【讨论】:

  • 感谢您的回答。我很抱歉,但这个解决方案是不畅销的。如果我们只更改User 实体,则更正其他组件不会花费太多时间,但是如果要大规模重写业务逻辑,则删除除业务逻辑之外的所有内容并重新创建 if 会容易得多。跨度>
猜你喜欢
  • 2022-07-23
  • 2020-08-14
  • 1970-01-01
  • 1970-01-01
  • 2021-10-03
  • 1970-01-01
  • 2014-03-31
  • 2021-04-10
  • 2018-12-29
相关资源
最近更新 更多