首页 文章

Typescript字符串文字联合类型

提问于
浏览
0

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

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

我要做的是将这些字符串定义在某种数组中的其他位置,然后在属性定义中使用该数组 . 所以类似于:

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

我明白以上是不可能的,但这是一般的想法 . 打字稿能提供完成这项工作的任何东西吗?

3 回答

  • 0

    不,您不能为数组中的字符串定义有效值,并在编译时检查它 .

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

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

    对此:

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

    一旦编译器运行完毕,你的类型就不再存在了!它只是JavaScript,除了你明确写的内容之外没有添加额外的逻辑 . 您无法将有效值存储在数组中,因为在代码实际运行之前,不会对数组的内容进行求值,此时已执行类型检查并且已丢弃类型 .

    因此,如果要检查字符串是否与数组中的值匹配,则需要实际编写一些在运行时执行该检查的代码 .

  • 1

    这取决于你打算如何使用它,但字符串枚举可能会给你你想要的东西:

    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'];
    
  • 1
    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));
    

相关问题