【问题标题】:Typescript - how do you deal with common properties between two interface?Typescript - 你如何处理两个接口之间的公共属性?
【发布时间】:2021-10-30 14:48:35
【问题描述】:

我有一个 interfaceA1 和 interfaceB 有一些共同的属性

interface A1 {
  id : string,
  version: number,
  data: userData,
  createdBy: string
}

interface userData {
  data: string,
  status: string
}

interface B {
  id : string,
  version: number,
  definition : JSON
}

所以,在interfaceA1和interfaceB之间有一些id,version等属性是通用的

我有一个 interfaceA 类型的变量,具有以下值

let interfaceA1Data: interfaceA1 = {
  id : '123abc',
  version: 1,
  data: {
    data: 'value',
    status: 'value'
  },
  createdBy: 'me'
}

我还有一个 interfaceB 类型的变量,刚刚声明了

let interfaceBData: interfaceB

现在我想将常用属性的值从 interfaceA1Data 复制到 interfaceBData。非通用属性应添加到定义属性中。因此,最终 interfaceBData 将保存以下值。

interfaceBData = {
  id : '123abc',
  version: 1,
  definition: {
    data: {
      data: 'value',
      status: 'value'
    },
    createdBy: 'me'
  }
}

如何在打字稿中实现这一点?

转换器应该是通用的,如果我有一个 interfaceA2,如何转换为 interfaceB 类型。在所有情况下,目标接口都相同,只有源接口不同。

interface A2 {
  id : string,
  version: number,
  value: valueType,
  createdBy: string
}

interface valueType {
  type: string,
  requester: string
}

【问题讨论】:

  • “属性”是错误的术语。 TypeScript+JavaScript 不是 Python:对象成员被称为“属性”。
  • TypeScript 在 type-erasure 的基础上工作(类型不会在运行时具体化),因此 TypeScript 不能自己过滤属性 - 你需要复制手动设置值 - 尽管您可以通过明智地应用 Object.assign 来减少工作量。
  • 嗨,我可以得到一些如何实现这一点的入门代码吗?

标签: javascript typescript interface clone


【解决方案1】:

如果两个接口之间有意重叠,则可能值得将公共属性提取到单独的接口中。例如:

interface Versioned {
  id: string,
  version: number
}

interface userData {
  data: string,
  status: string
}

interface valueType {
  type: string,
  requester: string
}

interface A1 extends Versioned {
  data: userData,
  createdBy: string
}

interface A2 extends Versioned {
  value: valueType,
  createdBy: string
}

现在,您可以像以前一样继续创建“B”接口,只需使用 definition 属性作为 Object 再次扩展 Versioned:

interface B extends Versioned {
  definition: Object
}

...但您可能希望通过将其转换为通用接口来提供额外的严格性,如下所示:

interface Serialized<T extends Versioned> extends Versioned {
  definition: Omit<T, keyof Versioned>
}

现在您可以轻松地为任何扩展版本的类型/接口编写转换器函数,将其转换为序列化的特定形状:

function transformer<T extends Versioned>(
{id, version, ...args}: T): Serialized<T> {
  return {
    id, version,
    definition: {...args}
  }
}

这里是TS Playground link

【讨论】:

  • 您好,您提到的转换器逻辑是特定于接口的。我现在已经编辑了我的问题,你能检查一下现在如何实现吗?
  • 不确定你的意思。只要预期的输出格式相同,这适用于 A 和 A2。
  • 是的,预期的输出格式是相同的,无论源接口的非公共属性将进入接口B的定义
  • 如果你想统一(它是一个单一的接口)并且足够灵活以支持两个“输入”接口,interfaceB 的定义应该是什么样子?您能否显示在尝试时会出现错误的代码?
  • 我想我想通了(并在附加的链接中显示了这一点)。这个想法是,您创建一个通用接口 B 而不是单个具体接口 B,然后使用这个通用接口创建一个模板转换器,将两种格式 - 输入一种和输出一种 - 连接在一起。
猜你喜欢
  • 2020-12-13
  • 2021-09-10
  • 1970-01-01
  • 2010-11-16
  • 1970-01-01
  • 1970-01-01
  • 2020-09-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多