数组类型联合的问题

时间:2018-09-09 23:50:56

标签: arrays typescript types

以下是我正在使用的某些类型(此对话已简化):

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)
}

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

  

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

我的分析: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(以我想要的灵活方式),该conda保留了更多类型信息以更严格地使用。

1 个答案:

答案 0 :(得分:2)

尝试一下:

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进行匹配并获得两个name = ["Hetty", "Poppy", "Blue Skies", "Bay View", "Happy Days", "Summer Joy", "Walkers Rest", "Bertie","Green Forest Lodge", "Coppice Lodge" ] cap = [4, 4, 4, 6, 6, 6, 8, 8, 10, 10] peak = [400, 400, 500, 650, 695, 800, 950, 1050, 1200, 1500] offpeak = [250, 250, 350, 500, 550, 600, 750, 850, 950, 1150] onoff = False cost = 0 print("Here are our avaliable lodges") for elem in name: print("- " + elem) desired_room = (str(input("Enter The Name Of The Room You Would Like To Book: "))).lower() while True: for i in range (0,10): if desired_room == name [i].lower(): print("Name: ", name[i]) print("Capacity: ", cap[i]) print("Off Peak Rate: 0" + str(offpeak[i])) print("Peak Rate: 0" + str(peak[i])) exit print("Invalid Room Name Entered Try Again") desired_room = (str(input("Enter The Name Of The Room You Would Like To Book: "))).lower() week = int(input("Enter The Week Your Stay Starts ")) 冲突的推论。对于工会的两种情况。