数组类型的联合问题

问题描述 投票:1回答:1

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

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; readonly inside:string; } [] | {readonly outside:NodeId;只读内部:CellId; } []'不能赋值给'{readonly outside:NodeId; readonly inside:string; } []”。

我的分析: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个回答
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的两个相互矛盾的推论,而只是要求数组具有您正在寻找的密钥,这对于两个联合的情况都是如此。

© www.soinside.com 2019 - 2024. All rights reserved.