TypeScript 异步函数的类型不处理像普通函数那样的void赋值,

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

TypeScript 版本: 3.4.0-dev.201xxxxx
搜索词:
代码

const w: void = "";

const x: () => void = () => "";

const y: () => Promise<void> = async () => "";

function a(): void {
    return "";
}

async function b(): Promise<void> {
    return "";
}

const y2: () => Promise<() => void> =  async () => () => "";

function a2(): () => void {
    return () => "";
}

function b2(): Promise<() => void> {
    return () => "";
}

预期行为:

一般来说,它们都应该是错误,或者它们都不应该是。

实际行为:

我们有一个特殊的 "返回 void 的函数" 规则,允许 () => "" 可以赋值给 () => void ,但这并不适用于异步场景,所以一个 async () => "" 不能赋值给一个 () => Promise<void>

实验链接

w1jd8yoj

w1jd8yoj1#

我们有两条规则来管理上述内容:

  1. 返回函数不应返回非 undefined 的值。
  2. A function type whose return value is void is treated as though that void were unknown,用于可分配性。 这导致了一个令人讨厌的不一致性,即使带有注解返回void的函数语句/表达式被检查为undefined-ness,但被分配给具有函数类型注解的函数表达式的const却不以相同的方式进行检查。另外,第二条规则在某些情况下无法影响异步函数,因为它们 *不*返回void,而是返回Promise` 。
lb3vh1jj

lb3vh1jj2#

这已经让我在为miniSphere编写类型时感到痛苦了。一般来说,我喜欢这样的规则:对于赋值目的,void 返回的行为相当于 any ,因为它在HOF场景(回调等)中很有用,而且我不能用异步函数获得相同的行为让我感到沮丧。

z3yyvxxp

z3yyvxxp3#

这似乎有点棘手:如果我们让 void 赋值规则适用于 Promise<void>,那么它是否会影响具有 void 类型参数的任何泛型?我不确定这是否可取...
即使是这样...当类型参数是协变的时候怎么办?或者不变?变化是否会影响它?这是一个相当大的难题。

mec1mxoz

mec1mxoz4#

实际上,我认为void只需要表现得像unknown一样,除了我们还有lint级别的检查,试图禁止在预期返回位置类型为void的实现中返回实值。

nwwlzxa7

nwwlzxa75#

我不知道,我觉得现在 voidany 的二元性有点优雅。😃

  • any :随你所愿,我不打扰你,但运行时错误是你现在的问题
  • void :我会把任何东西放在这里,不要试图阻止我(通过检查值)否则
yzckvree

yzckvree6#

我已经注意到,在以下情况下,void的行为并不符合预期:
这应该抛出一个错误,因为 () => () => void 不等于 () => void

type BasicFn = () => void
// Should throw an error but doesn't
const x: BasicFn  = () => () => console.log('hello')

这个bug让我花了好几个小时试图弄清楚我做错了什么。
发现 () => () => {} 应该改为 () => {} 并不容易,尤其是当你期望TS能检测到类似这样的类型冲突问题时。

相关问题