javascript - 具有依赖类型的 Typescript 联合

标签 javascript typescript

如果我有以下包含函数及其参数的联合,我该如何调用它?

type Wrapper = {
  fn: (a: string) => void
  arg: string
} | {
  fn: (a: number) => void
  arg: number
}

let foo!: Wrapper
foo.fn(foo.arg) // Error Type 'string' is not assignable to type 'never'.

我不知道怎么调用它。我尝试过的所有内容基本上都归结为强制转换(例如转换为 (a:any) => void),如果必须的话我可以这样做,但我觉得我不应该这样做必须这样做。

这个函数可以不强制转换就调用吗?

编辑:为了澄清,我想问的是是否存在不涉及更改 Wrapper 定义的解决方案。

最佳答案

您可以使用条件类型来消除类型歧义。不幸的是,它需要你基本上再次复制你的包装器联合类型,如果你有更多的东西需要检查,你的条件类型将变得非常丑陋。但它确实可以让您避免强制转换(某种程度上)。

type Wrapper = {
  fn: (a: string) => void
  arg: string
} | {
  fn: (a: number) => void
  arg: number
}

type Disambiguate<W extends Wrapper> = W['arg'] extends string
  ? { fn: (a : string) => void, arg: string }
  : { fn: (a: number) => void, arg: number };

let foo!: Disambiguate<Wrapper>

// The compiler is satisfied. No error here.
// foo can only be one of the branches in the conditional type.
foo.fn(foo.arg);

关于javascript - 具有依赖类型的 Typescript 联合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63994807/

相关文章:

javascript - 从数组中获取元素位置

javascript - (Angular 12)目标环境不支持动态 import() 语法,因此无法在脚本中使用外部类型 'module'

javascript - 引用错误 : Can't find variable: exports

javascript - 从 rxjs 订阅返回一个函数

Angular Universal : How to resolve missing names, 模块和其他奇怪的东西

javascript - JQuery 选择器重写

javascript - 在 AngularJS 中保留路由更改的滚动位置?

javascript - 浏览器在地理定位请求上允许/禁止按钮

javascript - requestAnimationFrame回调中的es6类 "this"?

typescript - 在 vue3 中使用 headless ui 的 Modal