我想将字符串缩小为字符串文字联合。换句话说,我想检查字符串是否是我的文字联合的可能值之一,这样就可以了(如果操作符type lit = "A" | "B" | "C";
let uni: lit;
let str = "B";
if(str couldbe lit){
uni = str;
} else {
doSomething(str);
}
存在)。
if (str instanceof lit)
我如何实现这一目标?
我尝试使用keyof
,但这似乎不起作用。使用switch
迭代字符串联合也不起作用,因为允许的值本身不是键。
一种方法是使用lit
为每个可能的值使用一个案例,但如果# -*- coding: utf-8 -*-
允许的值发生更改,则可能会导致细微的错误。
答案 0 :(得分:1)
您可以使用User-Defined Type Guards。
type lit = "A" | "B" | "C";
let uni: lit;
let str = "B";
function isLit(str: string): str is lit {
return str == "A" || str == "B" || str == "C";
}
function doSomething(str: string) {
}
if (isLit(str)) {
uni = str;
}
else {
doSomething(str);
}
添加强>
为避免重复编辑,class
可用于编译时和运行时。现在你所要做的就是只编辑一个地方。
class Lit {
constructor(public A = 0, public B = 0, public C = 0) {}
}
type lit = keyof Lit;
let uni: lit;
function isLit(str: string): str is lit {
let lit = new Lit();
return (str in lit) ? true : false;
}
答案 1 :(得分:1)
这是我对类型保护和strictNullChecks
关闭的问题的处理(这是对项目的限制;如果此选项为true
,TS将需要对{{1} }。
第switch/case
行保证更改const _notLit: never = maybeLit;
类型时还需要更新lit
。
该解决方案的缺点是,随着联合类型switch/case
的增长,它变得非常冗长。
lit
如果可能,此任务更适合type lit = "A" | "B" | "C";
function isLit(str: string): str is lit {
const maybeLit = str as lit;
switch (maybeLit) {
case "A":
case "B":
case "C":
return true;
}
// assure exhaustiveness of the switch/case
const _notLit: never = maybeLit;
return false;
}
,或者如果您需要enum
并且不介意创建基础枚举进行检查,则可以创建如下类型的类型防护:
type
答案 2 :(得分:1)
如果你和我一样讨厌 switch case:
由于 TypeScript 3.4 – const assertions 也可以从字符串数组中生成联合类型 ^_^
const list = <const>["A", "B", "C"];
type Lit = typeof list[number]; // "A" | "B" | "C"
function isLit(str: string): str is Lit {
return !!lits.find((lit) => str === lit);
}