Typescript字符串字面量联合类型

5

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

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

我试图做的是在其他地方定义这些字符串,放入某种类型的数组中,然后仅在属性定义中使用该数组。类似以下内容:

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

我知道上述内容不可能实现,但这是一般思路。TypeScript有提供任何能够胜任此工作的工具吗?
5个回答

6

自 TypeScript 3.4 起,您可以使用 const 断言 从运行时值生成类型。

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

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'];

1
不,你不能在数组中定义字符串的有效值并在编译时进行检查。当你第一次通过TypeScript编译器运行示例时,原因变得更加明显 - 它从这个状态转变为:
class Test {
    public reaction?: 'haha' | 'wow' | 'angry' | 'sad' | 'like' = 'haha';
}

To this:

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

一旦编译器完成运行,您的类型就不再存在了!它只是JavaScript,除了您明确编写的内容之外,没有添加任何额外的逻辑。您无法将有效值存储在数组中,因为数组的内容直到代码实际运行时才会被评估,此时类型检查已经完成并且类型已被丢弃。
因此,如果您想要检查字符串是否与数组中的某个值匹配,您需要编写一些在运行时执行该检查的代码。

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

1
您可以使用 type 来命名联合类型。
type Reaction = 'haha' | 'wow' | 'angry' | 'sad' | 'like';
const reaction?: Reaction = 'haha';

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接