node.js - TypeScript:作为其他接口(interface)联合的通用接口(interface)

标签 node.js typescript generics interface

我想创建一个通用接口(interface),其属性表示来自其他接口(interface)的属性的联合。

假设我有两个接口(interface)

interface A {
    something: string;
    somethingElse: number;
}

interface B {
    something: Array<string>;
}

我不想把接口(interface) C 写成

interface C {
    something: string | Array<string>;
    somethingElse?: number;
}

因为这意味着每当我修改接口(interface) AB 时,我也需要手动修改接口(interface) C .

根据我在 TypeScript 文档中看到的以及 Stack Overflow 上的答案,我应该声明一个新类型

type unionOfKeys = keyof A | keyof B;

并实现通用接口(interface)形式

interface GenericInterface {
    <T>(arg: T): T;
}

我的思路是

interface C {
    <T extends unionOfKeys>(arg: T): T extends unionOfKeys ? A[T] | B[T] : any
}

但由于许多属性及其类型不匹配而失败。

我将不胜感激任何形式的帮助。谢谢。

最佳答案

我认为以下版本MergeUnion<T>可能会按照您的意愿行事:

type MergeUnion<T> = (
  keyof T extends infer K ? [K] extends [keyof T] ? Pick<T, K> & {
    [P in Exclude<(T extends any ? keyof T : never), K>]?:
    T extends Partial<Record<P, infer V>> ? V : never
  } : never : never
) extends infer U ? { [K in keyof U]: U[K] } : never;

type C = MergeUnion<A | B>;
// type C = { 
//  something: string | string[]; 
//  somethingElse?: number | undefined; }
// }

这与另一个答案相似,因为它找到了 T 的所有成分的所有键的并集。 (称之为 UnionKeys ,定义为 T extends any ? keyof T : never )并返回一个包含所有这些类型的映射类型。不同的是,这里我们还找到了T的所有成分的所有键的交集。 (称之为 IntersectKeys ,定义为 keyof T )并拆分键 T成两组键。来自交叉点的那个存在于每个成分中,所以我们可以做 Pick<T, IntesectKeys>获取公共(public)属性。其余的,Exclude<UnionKeys, IntersectKeys > 在最终类型中是可选的。

更新 2019-08-23:下面提到的错误似乎已从 TS3.5.1 开始修复

它非常丑陋,如果我感觉好点,我会清理它。问题是,当所有成分中出现的任何属性本身都是可选的时,仍然存在问题。有一个 bug in TypeScript (自 TS3.5 起){a?: string} | {a?: number} 中的位置, a属性被视为必需 属性,例如 {a: string | number | undefined} ,而如果任何成分将其视为可选,则将其视为可选更为正确。该错误会渗透到 MergeUnion :

<罢工>
type Oops = MergeUnion<{a?: string} | {a?: number}>
// type Oops =  { a: string | number | undefined; }

我没有一个不是更复杂的好答案,所以我就到此为止。

也许这足以满足您的需求。或者@TitianCernicova-Dragomir 的回答可能足以满足您的需求。希望这些回答对你有帮助;祝你好运!

Link to code

关于node.js - TypeScript:作为其他接口(interface)联合的通用接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56296506/

相关文章:

node.js - 如何下载 AWS 证书以将其与 NodeJS 一起使用

reactjs - React 组件正在进行无限的 API 调用

typescript - 如何在函数中使用传播作为参数?

typescript - 我可以使用 Typescript 泛型来过滤对象中的键吗?

c# - 通用抽象类继承

javascript - 在express.js中设置cookie出现j : prefix

node.js - mongodb查找计算字段

node.js - 使用 NGINX 提供静态文件时如何响应 Node.js 的 404?

c++ - 编译器模板实现会引入循环依赖吗?

java - 使用通配符返回通用类型对象的列表