TypeScript 无法对返回"永远不会"的函数执行类型缩小,

gudnpqoy  于 6个月前  发布在  TypeScript
关注(0)|答案(6)|浏览(44)

Bug报告

🔎 搜索词

类型缩小从不

🕗 版本与回归信息

  • v4.5.2
  • v4.4.4
  • v4.3.5
  • v4.2.3
  • v4.1.5
  • v4.0.5
  • v3.9,7

这是我尝试的每个版本的行为,我查阅了有关此问题的FAQ条目。

⏯ Playground链接

带有相关代码的Playground链接

💻 代码

type ShouldNeverReturnFunction = () => never;

let shouldNeverReturn: ShouldNeverReturnFunction | null = null;

function foo(): never {
  if (shouldNeverReturn === null) {
    throw new Error('The "shouldNeverReturn" function was not initialized.');
  }

  shouldNeverReturn();
}

🙁 实际行为

TypeScript编译器拒绝编译这段代码。

🙂 预期行为

我希望TypeScript编译器能够编译这段代码。
错误信息表示 foo 函数具有“一个可达的终点”,但这显然是错误的,因此TypeScript编译器似乎喝醉了。🍺🥴

bwleehnv

bwleehnv1#

#32695 提到:
函数名解析为具有 asserts 返回类型的函数类型,或者具有显式的 never 返回类型注解。
shouldNeverReturn 没有解析为这样的函数,它只是后来被缩小到一个。不幸的是,PR 没有提到联合体,所以不清楚这是有意的(我的猜测)还是不是。

yacmzcpb

yacmzcpb2#

我认为原则上可以将检查范围扩大到工会,但这似乎是一个相当罕见的情况。return shouldNeverReturn();的旧解决方法在这里效果很好。如果经常遇到这种情况,我们可以进一步研究。

brccelvz

brccelvz3#

我刚刚在重构一个日志函数时遇到了这个问题,我不得不抛出传递给它的错误对象。例如,我的代码看起来像这样:

if (!obj.requiredProp) {
  const error = new Error('requiredProp is required');
  logger.error(error.message)
  throw error;
}

someFn(obj.requiredProp);

我的新代码添加了一个 throw 函数,使用方式如下:

declare const logger: { throw: (error: unknown) => never };

if (!obj.requiredProp) {
  logger.throw(new Error('requiredProp is required'));
}

someFn(obj.requiredProp); // argument of type 'string | null' is not assignable to parameter of type 'string'

在这里我期望进行一些类型缩小,但我得到了评论中提到的错误。

z9zf31ra

z9zf31ra4#

今天我遇到了另一个类似的问题。我不能100%确定是否是同一个问题,但它看起来很像。
请考虑以下代码片段:

function checkFoo(something: string): boolean {
  if (something === "foo") {
    return true;
  }

  if (something === "bar") {
    return false;
  }

  throw new Error("Unknown something.");
}

它运行得很好!👍

function error(msg: string): never {
  throw new Error(msg);
}

function checkFoo(something: string): boolean {
  if (something === "foo") {
    return true;
  }

  if (something === "bar") {
    return false;
  }

  error("Unknown something.");
}

当开启"noImplicitReturns"编译器标志时,这段代码会失败。❌
它提示“并非所有代码路径都返回值”,这是错误的,因为所有代码路径都以与第一个代码片段完全相同的方式返回,但TypeScript并不足够智能地意识到这一点。

j2qf4p5b

j2qf4p5b5#

好的,Retsam帮助我意识到,如果在error函数上添加一个返回类型注解为never,代码就可以编译。而TypeScript编译器无法自动完成这一点的原因是Ryan Cavanaugh提出的discussed here。所以我猜可以忽略"noImplicitReturns"这个事情。(但是类型缩小仍然是一个问题。)

jobtbby3

jobtbby36#

@RyanCavanaugh,你觉得这是否是社区成员可以贡献的事情?我特别感兴趣的是如何解决上面提到的@kherock的使用案例。

相关问题