首页 文章

Typescript - 如何检查给定值是否在联合类型数组中

提问于
浏览
5

我有一个给定的联合类型的数组,然后想检查数组中是否包含来自联合类型的超集的字符串(运行时检查):

const validOptions: ("foo" | "bar")[] = ["foo", "bar"]
type IArrType = typeof validOptions[number]
const key: IArrType | "alien" = "alien" // Rather: some random function
const isKeyInArr = validOptions.indexOf(key) > -1 // Error: "alien" is not assignable to "foo" | "bar"

// Fix 1:
const isKeyValidCast = validOptions.indexOf(<IArrType>key) > -1 
// Fix 2:
const isKeyValidExplicit = 
      key === "alien" ? false : validOptions.indexOf(key) > -1 // OK: type guard magic

修复1可以,但不是很优雅 . 修复2愚弄编译器,但是误导和低效的运行时 . 在我的例子中,“外来”字符串类型只是不在联合类型中的任何字符串的占位符 .

有没有什么方法可以在没有强制转换或显式测试的情况下编译?表达式可以否定,以便我们让这个“类型后卫”起作用吗?

顺便说一句:这个非常酷的答案展示了如何从值列表构造一个类型化的元组:Typescript derive union type from tuple/array values

1 回答

  • 3

    最大的问题是如何在不明确检查每个值的情况下处理非 ConfigurationKeys 的所有可能值 . 我将它们命名为Configuration,因为它是非常常见的场景 .

    你可以隐藏你自己的守护函数后面的逻辑告诉编译器:我可以处理类型检查,相信我 . 它被 value is ConfigurationKeys 返回类型识别 .

    Code examplelive):

    type ConfigurationKeys = "foo" | "bar";
    
    function isConfiguration(value: string): value is ConfigurationKeys {
        const allowedKeys: string[] = ["foo", "bar"];
    
        return allowedKeys.indexOf(value) !== -1;
    }
    
    const key: string = "alien" // Rather: some random function
    
    if (isConfiguration(key)) { 
        // key => ConfigurationKeys
    } else { 
        // key => string
    }
    

    我发现编写自己的防护功能是非常干净的解决方案,可以使用Union类型 . 有时仍然需要类型转换,但是在这里你可以在单个代码段中隐藏转换和逻辑 .

    参考:

相关问题