typescript - Typescript 中的多种类型谓词

标签 typescript typescript-typings typescript-generics

我有一个案例,我经常同时检查 bool 值和另一个联合类型的值。虽然它们在逻辑上是相关联的,并且可以假设只检查一个,但我需要检查两个,以便 TS 编译器知道这两种类型。

let multiple: boolean
let value: Array<string> | string 
...
if (multiple && isArray(value)) {
  // TS knows multiple === true and value is an Array
}

有没有一种方法可以编写类型检查函数,其中类型谓词断言多个值?

像这样:

// Not valid Typescript
function isMulti (
  multi: boolean, 
  value: Array<string> | string
): (multi is true) && (value is Array<string>) {
  return multi && isArray(value)
}

在大多数情况下,我只需检查 isArray 就可以解决问题,但在某些情况下,我想重复使用上述检查。这可能吗?


回应@kaya3:

为了给出更准确的用例,我有类似下面的内容:

我可以将 multiplevalue 分配给具有 DiscriminatedUnion 类型的对象,但这增加了比我认为这需要的更多的复杂性。

type ValueType<M extends boolean> = M extends true ? Array<string> : string;

interface PropTypes<M extends boolean> {
  multiple: M,
  // more properties
}

type DiscriminatedUnion = {
  multiple: true,
  value: Array<string>
} | {
  multiple: false,
  value: string
}

function myFunction<M extends boolean>({
  multiple
}: PropTypes<M>) {

  let value: ValueType<M>;

  // ... later

  if (multiple) {
    // TS will not assert the type of `value` here
  }

  // Trying discriminated union
  // TS Error: Type '{ multiple: boolean; value: string | string[]; }' is not assignable to type '{ multiple: false; value: string; }'
  let obj: DiscriminatedUnion = {
    multiple,
    value
  }
}

最佳答案

目前无法通过这种方式解决您的问题; @jcalz 有用地指出有一个开放的 feature request为了它。也就是说,您的问题可能以不同的方式得到更好的解决。

对于几乎任何问题,例如“我有这两个值,我如何告诉 Typescript 它们的类型是相关的?”,答案是将它们作为对象中的属性放在一起。然后你可以使对象的类型成为一个可区分的联合,这样对其中一个属性的测试可以缩小整个对象的类型。

type DiscriminatedUnion =
    | {multiple: false, value: string}
    | {multiple: true, value: string[]}

declare let obj: DiscriminatedUnion;

if(obj.multiple) {
    // here, obj.value is narrowed to string[]
    obj.value
}

Playground Link

关于typescript - Typescript 中的多种类型谓词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69831102/

相关文章:

css - 在 Angular 中更新自定义复选框组件 View

typescript - 为什么 Typescript 在解构时无法推断出可区分的类型

javascript - 如何在 typescript 中获取 "this"类型

typescript - 如何将属性函数的返回类型推断为属性的类型?

typescript - 使用 Typescript 从 switch case 返回类型推断

typescript - Angular6 - 使用名称获取嵌套 FormGroup

git - 我应该推送已编译的 javascript 还是忽略它们?

typescript - 在 typescript 中使用关键字作为标识符

javascript - 在 JavaScript VSCode 项目中添加自定义类型文件

Typescript - 为什么没有相应地强制实现接口(interface)