使用一个计算属性创建一个TypeScript类

时间:2017-09-25 12:41:07

标签: json typescript

创建一个只有一个计算属性作为键的类是否有意义,以便我可以处理JSON响应?

我有以下问题,我想创建一篇博文。创建一个有3种不同的选项。

  • A)Blog Post EN
  • B)Blog Post GER
  • C)Blog Post FR

根据博文的不同,应该有不同的模板。

现在我希望有一个主视图,我可以方便地编辑所有帖子。

JSON就是这样的:

[
  {
    "B1": {
      "A": {
        "Headline": "Hello World",
        "Text": "This is a hello world text"
      },
      "B": {
        "Headline": "Hallo Welt",
        "Text": "Ein Hallo Welt Text"
      },
      "C": {
        "Headline": "Bonjour Monde",
        "Text": "Le monde est à toi."
      }
    }
  }
]

B1是唯一的博客帖子标识符。应将A,B,C视为模板键。如果“A”则表示我们想要使用模板A.

现在对于实际问题,我想使用TypeScript及其功能。

BlogPostIdObject类是否有意义?我只创建它以便有一种简单的方法将传入的JSON解析为具有特定形状的对象。

export class RootObject {
  blogposts: BlogPostIdObject[]
}

export class BlogPostIdObject {
  [templateIdObject: string]: TemplateIdObject
}

export class TemplateIdObject {
  Headline: string;
  Text: string;
}

1 个答案:

答案 0 :(得分:1)

在下文中,我将您的JSON样式对象文字分配给名为json的常量:

const json = [
  {
    "B1": {
      "A": {
        "Headline": "Hello World",
        "Text": "This is a hello world text"
      },
      "B": {
        "Headline": "Hallo Welt",
        "Text": "Ein Hallo Welt Text"
      },
      "C": {
        "Headline": "Bonjour Monde",
        "Text": "Le monde est à toi."
      }
    }
  }
];

您的类型定义存在一些问题。首先,假设您只想将JSON样式的对象分配给RootObject类型的变量,则不应使用class。您可以通过调用其构造函数来创建类的实例,如new RootObject();你不能只为它分配/转换一个对象文字。 TypeScript可以让你这样做,但你可能会在运行时遇到问题。相反,使用interfacetype,它们将接受对象文字。所以我们切换到interface

export interface RootObject {
  blogposts: BlogPostIdObject[]
}

export interface BlogPostIdObject {
  [templateIdObject: string]: TemplateIdObject
}

export interface TemplateIdObject {
  Headline: string;
  Text: string;
}

好的,我们来试试吧!

const interpretedJson: RootObject = json; // error!

哦,它抱怨json不包含名为blogposts的属性。它没有。实际上,您希望RootObject只是 一个BlogPostIdObject[]的数组,而不是拥有一个数组:

// note, changed to type alias instead of interface
export type RootObject = BlogPostIdObject[];

export interface BlogPostIdObject {
  [templateIdObject: string]: TemplateIdObject
}

export interface TemplateIdObject {
  Headline: string;
  Text: string;
}

让我们再试一次!

const interpretedJson: RootObject = json; // error!

现在抱怨json[0].B1TemplateIdObject不匹配。它没有,因为TemplateIdObject实际上根本没有模板ID;它只有HeadlineText属性。实际上,您希望TemplateIdObject拥有其键是某些字符串且其值具有HeadlineText属性的属性。让我们通过将TemplateIdObject拆分为键和值(我将其称为TemplateValuesObject)来解决问题:

export type RootObject = BlogPostIdObject[];

export interface BlogPostIdObject {
  [blogIdKey: string]: TemplateIdObject
}

export interface TemplateIdObject {
  [templateIdKey: string]: TemplateValuesObject
}

export interface TemplateValuesObject {
  Headline: string;
  Text: string;
}

const interpretedJson: RootObject = json; // okay

所以,现在它有效。万岁,我们都做完了,对吧?

嗯,我不知道。该定义不是很严格。

它会让您发布包含许多ID的博文,例如[{"B1": {...}, "B2": {...}, ...}]或零ID,例如[{}]。这样可以吗?如果没有,可能JSON结构本身并不好,因为JSON对象不是为了保存未知名称的单个属性而设计的。您应该考虑将JSON更改为更像[{"blogId":"B1", "templates":{"A"...}}],以便数组中的每篇博文都只有一个blogId和一组templates

它会让您拥有包含许多ID的模板,例如[{"B1":{"A": {...}, "B": {...}, "C": {...}, "D": {...}, ...}}]或没有ID,例如[{"B1": {}}]。这样可以吗?如果不是,那么它们应该是"A""B"还是"C"?如果是这样,您可以通过将TemplateIdObject更改为具有这些确切键来指定。

因此,如果您已完成或需要对类型定义或可能的JSON结构本身进行更多修订,则由您决定。希望有所帮助;祝你好运!