本文介绍了数组类型联合的麻烦的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Here are some types I'm using (simplified for this conversation):

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

此处的键: CodeCall DefinitionCall 各自包含一个输入"数组,这些输入具有重叠但不同的定义.

Key here: CodeCall and DefinitionCall each contain an array of "inputs", with overlapping but different definitions of what an input is.

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

Here's a useful function for my application:

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

这有效!但是,天哪,最好使用实用程序功能进行搜索.这是我喜欢的实用程序功能的签名:

This works! But gosh, it would be nice to use a utility function to do the search. Here's the signature of a utility function I like:

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

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

But if I try to use it like this,

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

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

I get an error! In particular, this error:

我的分析: call.inputs 的类型为 {readonly outside:NodeId;内部的readonly:字符串;} [] |{外部只读:NodeId;内部只读:CellId;} [] . findWith 可以通过以下任一方式调用:

My analysis: call.inputs has type {readonly outside: NodeId; readonly inside: string;}[] | {readonly outside: NodeId; readonly inside: CellId;}[]. findWith can be called with either:

  • T = {只读,外部:NodeId;内部只读:字符串;} ,K = 'outside'
  • T = {只读,外部:NodeId;内部只读:CellId;} ,K = 'outside'
  • T = {readonly outside: NodeId; readonly inside: string;}, K = 'outside'
  • T = {readonly outside: NodeId; readonly inside: CellId;}, K = 'outside'

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

But it can't be called with T = the union of these. I guess this is kinda reasonable – TypeScript has no way of knowing that I'm using arrays in a context in which this should make sense.

我一直想弄清楚如何键入 findWith 来完成这项工作.有任何想法吗?(谢谢您的帮助!)

I'm stuck figuring out how to type findWith to make this work. Any ideas? (Thanks in advance for any help!)

更新:感谢Matt在下面的有用回答.仅供以后参考:我最终实现了以下操作(使用lodash)...

Update: Thanks to Matt for his helpful answer, below. Just for future reference: I have ended up implementing this as follows (using 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)
}

通过调用更严格的 findWith 可以实现(以我想要的灵活方式)实现 hasWith ,我感到宽慰,该代码可以保存更多类型信息以用于更严格的使用./p>

I am relieved that hasWith can be implemented (in the flexible way I want) by calling a stricter findWith, which holds onto more type information for stricter uses.

推荐答案

尝试一下:

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

然后,而不是尝试将 T [] {readonly outside:NodeId;内部的readonly:字符串;} [] |{外部只读:NodeId;里面是只读的:CellId;} [] 并获得 T 的两个相互矛盾的推论,您只需要数组具有您要查找的键即可,这在两种情况下都适用

Then, instead of trying to match T[] against {readonly outside: NodeId; readonly inside: string;}[] | {readonly outside: NodeId; readonly inside: CellId;}[] and getting two conflicting inferences for T, you just require that the array have the key you are looking for, which it does for both cases of the union.

这篇关于数组类型联合的麻烦的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 17:02