关于 ts 中回调函数参数加上泛型限制后传入联合类型为什么会报错?

相关代码如下,在 use 函数中加入联合类型后就会告诉我 number 和 string 类型不兼容,求教应该怎样解决这个问题,换个写法的话我想要的是保留 use 的泛型

declare function use<T>(data: T, cb: (arg: T) => void): void

declare function cb1(arg: string): void
declare function cb2(arg: number): void

use('', cb1) // success
use(1, cb2) // success

const data: string | number = 9
const cb: typeof cb1 | typeof cb2 = cb1

use(data, cb) // error

我面临的实际问题是,我有一个工具函数,它会返回一个 变量 和 消费这个变量的函数,变量的类型和函数的入参是强关联的,都需要限制为同一个类型,而这两个返回值都会被另一个函数作为入参,当我的工具函数返回一个联合类型的时候就得到了错误,上面给的实例代码有点不符合实际情况,看看下面的代码应该能更好理解

declare function getCb():
  | { data: string; cb: (arg: string) => void }
  | { data: number; cb: (arg: number) => void }

declare function use<T>(props: { data: T; cb: (arg: T) => void }): void

use(getCb()) // error
阅读 690
avatarAI BotBETA

你遇到的问题源于 TypeScript 的类型系统。在你的代码中,cb 函数的类型被定义为可以接受 stringnumber 类型的参数。然而,当你尝试将 cb 作为参数传递给 use 函数时,你传入的数据 data 实际上是一个 stringnumber 的联合类型。这就引发了类型不匹配的问题,因为 stringnumber 是两种不同的类型,不能直接相互转换。

解决这个问题的一种方式是使用类型断言。你可以明确地告诉 TypeScript,你确信 data 变量的确切类型就是 stringnumber,这样就可以消除类型不匹配的错误。

下面是一种可能的解决方案:

declare function use<T>(data: T, cb: (arg: T) => void): void;

declare function cb1(arg: string): void;
declare function cb2(arg: number): void;

use('', cb1); // success
use(1, cb2); // success

const data: string | number = 9;
const cb: typeof cb1 | typeof cb2 = cb1; // you are sure that cb is either cb1 or cb2

// use type assertion
use(data as string | number, cb); // success

在这个解决方案中,我们通过使用类型断言 as 来告诉 TypeScript,我们知道 data 的确切类型是 string | number,所以它应该可以安全地传递给 use 函数。这样,我们就可以保留泛型,同时解决了类型不匹配的问题。

3 个回答

因为你的cb 类型是cb1的类型 但是data是number

传入 use 方法之后,data 被推断为 number 类型,cb 被推断为 (arg: string) => void 类型

而 use 方法的泛型 T 被推断为 string(具体为啥我也不太清楚)

ts推断出来了你的data是number类型 T泛型也是number类型,要接收cb的arg也就是number类型。但是你传进去的cb是cb1的类型 也就是arg是string类型
报错arg类型不匹配

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Microsoft
子站问答
访问
宣传栏