【发布时间】: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,
}>,
}
这里的关键: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;内部只读:字符串; }[] | { 外部只读: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