关于 typescript 里面的 never 类型求教!

26 天前
 hahaFck

never 类型通常表示不会发生的类型,但是下面官方提供的泛型例子有点看不明白 never 的用途了。

type GetReturnType<Type> = Type extends (...args: never[]) => infer Return
  ? Return
  : never;

这是一个泛型工具类,可以提取函数的返回值类型,但是函数的参数定义成 never 类型数组有些不懂了,看提供的例子,这个定义既能满足无参数函数,也能满足有参数函数。

type Num = GetReturnType<() => number>;
//type Num = number
type Str = GetReturnType<(x: string) => string>;
//type Str = string
type Bools = GetReturnType<(a: boolean, b: boolean) => boolean[]>;
//type Bools = boolean[]
677 次点击
所在节点    程序员
6 条回复
realJamespond
26 天前
写成 any[]不也行?
hahaFck
26 天前
@realJamespond 写成 any 我能理解,但是 never 不知道是什么意思,而且按照我的理解是这个函数定义是不支持传参的,但是例子的 type Str = GetReturnType<(x: string) => string>; 这段代码竟然也能通过,奇怪了。
realJamespond
26 天前
他这里 args: never[],后面用不上,只是限制参数为数组,不进行推测。如果后面要用到 args 推测应该不能写成 never 的
Pencillll
26 天前
这是 TS 里的一个不合理设计

函数的参数是逆变的,所以 (x: string) => string 可以赋值给 (...args: never[]) => infer Return 的原因是 never[] 可以赋值给 [string],而 never[] 可以赋值给 [string] 的原因是……就是这么设计的

其实在正常情况下 never[] 是不可以赋值给 [string] 的,但 TS 对于函数里的 ...arg 这种语法做了某些处理导致这种赋值成立

官方的原话是(第二段): https://github.com/microsoft/TypeScript/issues/48840#issuecomment-1270671527
SO 有个同样的问题: https://stackoverflow.com/q/78316282
Pencillll
26 天前
我根据官方的原话猜测一下 TS 的做法:TS 先假定两个函数的参数数量一致,在这种前提下可以把数组 never[] 当成和元组 [string] 长度一样的元组,也就是 [never],再尝试赋值,而 [never] 是可以赋值给 [string] 的,所以前面的赋值也就成立了
mark2025
23 天前
@Pencillll 参逆返协。所以有时候 callback 的入参还不能用 unknown 而是得用 any, 否则调用的时候就会报错说 unknown 不能赋值为 string (或者其它正常类型)....

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1036378

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX