在Typescript中,是否有一种方法可以使字符串数组像“或拆分类型”一样工作?

时间:2018-10-01 16:44:57

标签: typescript types

通过“或拆分类型” 是指string | number | boolean。如果您的名字更好,我将更新问题。

我正在一个包含标签列表的界面上工作,类似于:

type Tags = "big" | "small" | "sharp" | "dull";
interface Shape {
  name: string;
  tags: Tags[];
}

稍后在代码中,我想列出所有可能的标签。在我的实际代码中,标记的数量远远大于四个,因此我想使用类型断言来确保列出所有标记。我该怎么办?

我可以想象的两种方法是:

  1. 从“或拆分类型”创建数组,出于明显的原因(嵌套条件),这是不可能的。
  2. 根据字符串数组声明类型。这个似乎很可能,我知道document.createElement("a" | "div" | "span"...)可以做到这一点,尽管我找不到合适的关键字来弄清楚它叫什么。

我的理想是遵循以下原则:

// Not real code
const Tags = ["big", "small", "sharp", "dull"];
interface Shape {
  name: string;
  tags: Array<item in Tags>;
}

那么,有没有办法使字符串数组的作用类似于或拆分类型?

2 个答案:

答案 0 :(得分:1)

  

在我的实际代码中,标记的数量远远大于四个,因此我想使用类型断言来确保列出所有标记。我该怎么办?

我最近不得不这样做,我们有两种选择。

  1. 具有属性作为对象属性的对象
  2. 一个数组和一个接口,因此,每当您向标签添加新项目时,您既要添加到数组又要添加对象

这似乎是个人喜好问题

我会根据需要使用对象Tags来强制类型安全

class Tags {
    public one: string;
    public two: string;
    public three: string;
    constructor({ one, two, three }: Tags) {
        this.one = one;
        this.two = two;
        this.three = three;
    }
}

interface Shape {
    name: string;
    tags: Tags;
}

let a = new Tags({}); // <-- This will fail because is not type Tag
a = new Tags({ one: '1' }); // <-- This will fail because it hasn't type two or type three
a = new Tags({ one: '1', two: '2', three: '3' }); // <-- This will pass

我们做的第二个选择如下:

const TagsArray = ["big", "small", "sharp", "dull"]
interface Tags {
  big: string;
  small: string;
  sharp: string;
  dull: string;
}

在我们使用它们的任何地方或传递标签的地方,我们都将其作为对象传递:

interface Shape {
  name: string;
  tags: Tags;
}

与所有事物一样,用法都是depends on your application,对我们来说,我们需要将数组传递给某些服务,并以数组值作为属性对对象进行类型检查,因此我们选择了2,因为这会阻止将Array转换为通过Object.keys(Tags)和任何服务返回的密钥均使用Shape

进行检查

答案 1 :(得分:0)

我最终使用的解决方案是创建一个文件来容纳包含两个导出的所有标签:

  1. Tags类型,它是标签可以是的每个字符串的并集类型
  2. tagList数组,是{[key in Tags]: null}类型的对象的属性列表。此对象类型要求将每个标签都表示为道具(并且不能更多)。

export type Tags = "featured" | "design" | "fabrication" | "development" | "audio" 
| "imagery" | "social" | "leadership" | "writing" | "3d" | "interactive" | "work";

// the following typedef will assert that every tag is added as a prop
const tagsObject: {[key in Tags]: null} = {
    featured: null,
    design: null,
    fabrication: null,
    development: null,
    audio: null,
    imagery: null,
    social: null,
    leadership: null,
    writing: null,
    "3d": null,
    interactive: null,
    work: null,
}
// because the tagsObject must have all tags as props to pass type assertion
// tagList will always contain every tag
const tagList: Tags[] = Array.from(Object.keys(tagsObject)) as any;
export { tagList };