代码之家  ›  专栏  ›  技术社区  ›  Seph Reed

在Typescript中,有没有一种方法可以使字符串数组的行为类似于“或拆分类型”?

  •  0
  • Seph Reed  · 技术社区  · 7 年前

    “或拆分类型” string | number | boolean

    我正在开发一个包含标签列表的界面,类似于:

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

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

    1. 基于字符串数组断言类型。我知道这似乎是很有可能的 document.createElement("a" | "div" | "span"...) 做了一些神奇的事情,虽然我找不到合适的关键字来找出它的名字。

    我的理想是这样的:

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

    所以, 有没有一种方法可以使字符串数组的行为类似于或拆分类型?

    2 回复  |  直到 7 年前
        1
  •  1
  •   Claudiordgz    7 年前

    我最近不得不这么做,我们有两个选择。

    1. 一个数组和一个接口,所以每当您向标记中添加一个新项时,您都会同时添加到数组和对象中

    这似乎是个人喜好的问题

    我会用一个物体 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,因为这样可以防止通过将数组转换为键 Object.keys(Tags) 无论服务返回什么,都使用 Shape

        2
  •  0
  •   Seph Reed    7 年前

    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 };