【问题标题】:Can typescript infer type based on a conditional expression & constant?打字稿可以根据条件表达式和常量推断类型吗?
【发布时间】:2020-02-14 08:58:13
【问题描述】:

我很好奇 Typescript 在考虑可能的执行路径以确定函数的类型时付出了多少“努力”(因为没有更好的术语)。

例如,考虑以下代码:

function getValue() {
    if (false) {
        return 'never this string';
    }

    return 42;
}

因为false 永远不会是true,所以永远不会返回“never this string”,因此该函数 - 看起来 - 应该具有“number”类型。

但是,当我将该类型注释(“:数字”)添加到函数定义中时:

// test.ts
function getValue(): number {
    if (false) {
        return 'never this string';
    }

    return 42;
}

并编译它(tsc test.ts),我得到这个错误:

test.ts:3:9 - error TS2322: Type '"never this string"' is not assignable to type 'number'.

所以我的问题是:

是否可以让 Typescript 认为“数字”是 getValue 的正确返回类型? (并且,相关的,是否有可能让编译器不会抱怨字符串不能分配给一个数字?)可能还相关:编译 TS 代码时,可以让编译器只删除无法访问的代码和 然后运行它的类型评估?

【问题讨论】:

  • 不确定死代码消除是否由 TS 完成。既然您已经提出要求并且我考虑过,我认为它应该完成。考虑一个条件if (someVar && alwaysFalse),其中alwaysFalse 可以通过编程方式确定它总是错误的,但很难手动追踪。现在,您将默默地得到与您(有些错误)期望的不同的行为。如果你依赖类型推断,这反过来会影响其他东西,虽然 getValue 返回 number | string 但现在它只返回 number,这可能会在其他地方产生影响。
  • 假设函数在file1中,在file2内部使用了几次,然后被file3使用。因此,您坐在 file3 中,想知道为什么在为 typeof result == "string" 添加案例时会出现错误。您可以绝对收到有关死代码的警告,但即使是 Java 等其他语言也会将您的情况视为错误,因为它们确实会计算死分支的返回值。
  • 您甚至不需要if 来创建无法访问的代码;进一步简化为return "test"; return 42; 仍然给出"test" | 42 的返回类型。而第二个return 肯定是无法访问的。
  • 你是用--allowUnreachableCode 编译的吗?即使没有 number 缩小,示例代码对我来说也是一个错误。
  • @jcalz 感谢您指出这一点 - 出于某种原因,当我运行 tsc test.ts 时,编译器 (v.3.3) 不会显示无法访问的代码错误,但当我使用 tsc -p . 时会出现 (即使我的 tsconfig 明确表示 "allowUnreachableCode": false,)。

标签: typescript


【解决方案1】:

if 条件在编译时不会显式地为假,这是 TypeScript 评估返回类型的时候。因为计算 if 条件的表达式是在运行时确定的,而不是在编译时确定的,因此我们不应该期望 TypeScript 假定 getValue 函数永远不会返回字符串类型。

【讨论】:

  • 我不确定if(false) 在编译时和运行时的工作方式有何不同。
  • @VLAZ 我的回答更多是为了说明if(false)if(expression which evaluates to false at run-time) 没有什么不同,我们是否应该期望 TypeScript 猜测它会评估为 false 不会在编译时引发类型错误?
  • 不过,这从来都不是问题。它适用于可以在编译时确定为死的代码。是的,TypeScript 不可能在运行时消除死分支,但从来没有要求过。
  • 嗨@hector101,感谢您的建议! :) 我明白你关于 if 语句是在运行时执行的事实的观点。但是,在对我的问题的评论中提出了一个有趣的观点:Typescript is 实际上能够确定代码“无法访问”,我认为这意味着编译器确实对 @987654326 进行了基本评估@ 编译时的语句。 (但你是对的,有更复杂的表达式只能在运行时确定。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-20
  • 1970-01-01
  • 1970-01-01
  • 2018-06-09
  • 2019-09-15
  • 2020-03-28
  • 2020-04-02
相关资源
最近更新 更多