【问题标题】:Trouble with unions of array types数组类型联合的问题
【发布时间】:2019-02-14 09:36:41
【问题描述】:

以下是我正在使用的一些类型(为本次对话进行了简化):

export interface NodeId { readonly _nodeId: string }
export interface CellId { readonly _cellId: string }

export type Call = CodeCall | DefinitionCall

export interface CodeCall {
  readonly inputs: Array<{
    readonly outside: NodeId,
    readonly inside: string,
  }>,
}

export interface DefinitionCall {
  readonly inputs: Array<{
    readonly outside: NodeId,
    readonly inside: CellId,
  }>,
}

这里的关键:CodeCallDefinitionCall 各自包含一个“输入”数组,对输入的定义有重叠但不同的定义。

这是对我的应用程序有用的功能:

export function doesCallUseNode1(call: Call, nodeId: NodeId): boolean {
  for (let input of call.inputs) {
    if (input.outside === nodeId) {
      return true;
    }
  }
  return false;
}

这行得通!但是天哪,使用实用程序函数进行搜索会很好。这是我喜欢的实用函数的签名:

declare function findWith<T, K extends keyof T>(arr: T[], key: K, value: T[K]): boolean;

但如果我尝试这样使用它,

export function doesCallUseNode2(call: Call, nodeId: NodeId): boolean {
  return findWith(call.inputs, "outside", nodeId)
}

我得到一个错误!特别是这个错误:

类型参数'{ readonly outside: NodeId;内部只读:字符串; }[] | { 外部只读:NodeId;内部只读:CellId; }[]' 不可分配给类型为 '{ readonly outside: NodeId;内部只读:字符串; }[]'。

我的分析:call.inputs 的类型为 {readonly outside: NodeId; readonly inside: string;}[] | {readonly outside: NodeId; readonly inside: CellId;}[]findWith 可以通过以下任一方式调用:

  • T = {readonly outside: NodeId; readonly inside: string;}, K = 'outside'
  • T = {readonly outside: NodeId; readonly inside: CellId;}, K = 'outside'

但不能用 T = 这些的并集来调用它。我想这有点合理——TypeScript 无法知道我在应该有意义的上下文中使用数组。

我一直在弄清楚如何输入 findWith 来完成这项工作。有任何想法吗? (提前感谢您的帮助!)


更新:感谢 Matt 的有用回答,如下所示。仅供将来参考:我最终实现了如下(使用 lodash)...

export function findWith<T>(arr: Array<T>, key: keyof T, value: T[keyof T]): T | undefined {
  return _.find(arr, (o) => _.isEqual(o[key], value))
}

export function hasWith<K extends keyof any, V>(arr: {[key in K]: V}[], key: K, value: V): boolean {
  return !!findWith(arr, key, value)
}

我很欣慰hasWith 可以通过调用更严格的findWith 来实现(以我想要的灵活方式),它保留了更多类型信息以供更严格的使用。

【问题讨论】:

    标签: arrays typescript types


    【解决方案1】:

    试试这个:

    declare function findWith<K extends keyof any, V>(arr: {[P in K]: V}[], key: K, value: V): boolean;
    

    然后,与其尝试将T[]{readonly outside: NodeId; readonly inside: string;}[] | {readonly outside: NodeId; readonly inside: CellId;}[] 进行匹配并得到T 的两个相互冲突的推论,您只需要求该数组具有您要查找的密钥,这对于联合的两种情况都适用.

    【讨论】:

    • 非常感谢!我考虑过这样的事情,但错过了“[P in K]”符号。这很棒。
    猜你喜欢
    • 1970-01-01
    • 2019-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多