以下是我正在使用的一些类型(此对话简化):
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
每个都包含一系列“输入”,重叠但不同的输入定义。
这是我的应用程序的一个有用的功能:
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
:
{readonly outside: NodeId; readonly inside: string;}
,K = 'outside'
{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
来实现(以我想要的灵活方式),它可以保存更多类型的信息以供更严格的使用。
试试这个:
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
的两个相互矛盾的推论,而只是要求数组具有您正在寻找的密钥,这对于两个联合的情况都是如此。