【问题标题】:Typescript string literal union type打字稿字符串文字联合类型
【发布时间】:2018-04-28 23:27:46
【问题描述】:

我有一个类属性,其类型是多个字符串文字的联合:

public reaction? : 'haha' | 'wow' | 'angry' | 'sad' | 'like';

我想要做的是在某种数组的其他地方定义这些字符串,然后在属性定义中使用该数组。所以像:

allowedStrings = ['haha','wow','angry','sad','like'];
public reaction? : allowedStrings;

我知道以上是不可能的,但这是一般的想法。打字稿是否提供任何可以完成这项工作的东西?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    不,您不能为数组中的字符串定义有效值并在编译时对其进行检查。

    当您通过 TypeScript 编译器运行您的第一个示例时,其原因会变得更加明显 - 它来自以下:

    class Test {
        public reaction?: 'haha' | 'wow' | 'angry' | 'sad' | 'like' = 'haha';
    }
    

    到这里:

    var Test = (function () {
        function Test() {
            this.reaction = 'haha';
        }
        return Test;
    }());
    

    一旦编译器运行完毕,您的类型就不再存在了!它只是 JavaScript,除了您明确编写的内容之外没有添加任何其他逻辑。您不能将有效值存储在数组中,因为在代码实际运行之前不会评估数组的内容,此时类型检查已经执行并且类型已被丢弃。

    因此,如果您想检查字符串是否与数组中的值匹配,您实际上需要编写一些在运行时进行检查的代码。

    【讨论】:

      【解决方案2】:

      这完全取决于您打算如何使用它,但是 字符串枚举 可能会为您提供所需的内容:

      enum ReactionKind {
          haha = 'haha',
          wow = 'wow',
          angry = 'angry',
          sad = 'sad',
          like = 'like'
      }
      
      const reaction: ReactionKind = ReactionKind.angry;
      
      // Get the string value  
      const stringValue = ReactionKind[reaction];
      
      // Get the Enum from a string
      const enumValue = ReactionKind['wow'];
      

      您仍然可以在需要的地方使用纯字符串值,但您可以将其用作类型和运行时值,这似乎是您所追求的。

      您还会注意到,对于字符串枚举,如果您在映射到枚举时使用字符串键,它将被检查...只要您使用的是--noImplicitAny

      // Error
      const enumValue = ReactionKind['wat'];
      

      【讨论】:

        【解决方案3】:
        enum Reaction {
            'haha',
            'wow',
            'angry',
            'sad',
            'like'
        }
        
        let reaction: keyof typeof Reaction;
        reaction = 'angry'; // Fine
        // reaction = 'whatever'; // Error
        

        看起来上面应该做你想要的。如果还需要一个字符串数组,可以按如下方式获取:

        const allowedStrings = Object.keys(Reaction).filter(k => Number.isNaN(+k));
        

        【讨论】:

          【解决方案4】:

          从 TypeScript 3.4 开始,您可以使用 const assertions 从运行时值生成类型。

          const allowedStrings = ['haha', 'wow', 'angry', 'sad', 'like'] as const;
          type AllowedString = typeof allowedStrings[number]; // [number] is important here
          
          // We can freely map over values
          const mapped = allowedStrings.map((s) => s.toUpperCase());
          
          // And use generated type to create type-safe functions
          const process = (s: AllowedString) => {
            // Type of s is
            //    s: "haha" | "wow" | "angry" | "sad" | "like"
            return s;
          };
          

          【讨论】:

            【解决方案5】:

            您可以使用type 来命名联合类型。

            type Reaction = 'haha' | 'wow' | 'angry' | 'sad' | 'like';
            const reaction?: Reaction = 'haha';
            

            【讨论】:

              猜你喜欢
              • 2019-02-22
              • 1970-01-01
              • 1970-01-01
              • 2021-07-02
              • 2020-06-07
              • 2021-08-01
              • 1970-01-01
              • 2018-12-07
              相关资源
              最近更新 更多