将字符串缩小到字符串文字并集
Posted
技术标签:
【中文标题】将字符串缩小到字符串文字并集【英文标题】:Narrowing string to string literal union 【发布时间】:2017-10-15 17:21:27 【问题描述】:我想将字符串缩小为字符串文字联合。换句话说,我想检查字符串是否是我的文字联合的可能值之一,以便这将起作用(如果运算符 couldbe
存在)。
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
s 允许的值发生变化,这可能会导致细微的错误。
【问题讨论】:
lit
类型在运行时不存在,因此您不能这样使用它。也许改用枚举?
关于switch语句注释,见answer。
@NitzanTomer 这实际上是一个非常好的主意,看起来更清晰,更容易理解。
【参考方案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;
【讨论】:
嗯,这比 switch 语句好一点,但它仍然存在当lit
s 允许的值更改时可能忘记更新类型保护的问题。
我为我的答案添加了另一个解决方案。
如果绝对必须使用文字联合,我非常喜欢您的第二种解决方案。不过,似乎更好的方法是切换到enum
s。【参考方案2】:
这是我对类型保护和关闭strictNullChecks
问题的看法(这是对项目的限制;如果此选项为true
,TS 将要求对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
并且不介意创建底层枚举以进行检查,您可以创建类似这样的类型保护:
enum litEnum
"A",
"B",
"C",
type lit = keyof typeof litEnum;
function isLit(str: string): str is lit
return litEnum[str] !== undefined;
【讨论】:
【参考方案3】:如果您像我一样讨厌开关盒: 因为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);
【讨论】:
以上是关于将字符串缩小到字符串文字并集的主要内容,如果未能解决你的问题,请参考以下文章