打字稿:文字类型的用户定义类型防护?

时间:2019-04-25 13:14:30

标签: typescript

注意:我是打字稿新手。在发布之前,我阅读了docs有关预付款类型和type guards的信息。此外,我还阅读了一些相关的S.O.问题(例如user defined type guards [typescript]How to write a user defined type guard for "string" | "literal" | "types"?

与我的问题最相似的是后面的问题,其中您可能在文字上具有某种自定义类型(在这种情况下为string,但解决方案也应适用于number),例如

type Format = 'JSON' | 'CSV' | 'XML'

在第二个问题中,用户询问打字稿的keyof关键字的解决方案,而 @Ryan Cavanaugh answer通过将类型从literalinterface并检查界面的键:

// copy-pasted from answer for convenience
interface McuParams {
    foo, bar, baz;
}
function isKeyOfMcuParams(x: string): x is keyof McuParams {
    switch (x) {
        case 'foo':
        case 'bar':
        case 'baz':
            return true;
        default:
            return false;
    }
}

我的问题特别是是否有一种方法可以使用类型本身来进行用户定义的类型保护,例如

const isFormat = (maybe:String|Format): maybe is Format => /* something goes here */

据我所知,以下操作无效(仅替换/* something goes here */):

// 1
/* 
 * As stated in the docs "The right side of the instanceof needs to 
 * be a constructor function" but we have a literal
 */
maybe instaceof Format

//2
/* As stated in the docs "typename" must be "number", 
 * "string", "boolean", or "symbol" 
 */
typeof maybe === 'format'


//3
/* no idea */
(<Format>maybe)

@Ryan Cavanaugh 的答案是唯一可行的解​​决方案吗?似乎非常冗长...

1 个答案:

答案 0 :(得分:2)

最好的方法是从 value 导出 type Format,就像包含所有Format文字的数组一样。有a number of ways to do this。假设您使用的是TS3.4 +,我将展示最简单的方法:

const formats = ['JSON', 'CSV', 'XML'] as const;
type Format = typeof formats[number];

您可以验证Format与以前的相同。现在,有了数组,您就可以使用它来构建类型防护:

function isFormat(x: string): x is Format {
    // widen formats to string[] so indexOf(x) works
    return (formats as readonly string[]).indexOf(x) >= 0;
}

这应该可以正常工作,并且不会太冗长(或者至少它不会在任何地方重复字符串文字)。希望能有所帮助;祝你好运!