【问题标题】:Dynamic type guard functions动态类型保护函数
【发布时间】:2020-09-16 18:52:23
【问题描述】:

我想创建一个类型保护函数来检查对象中的特定键是否具有例如string 值。如果我知道键名,这很容易:

const data: object = { a: 'one', b: 'two', c: 'three' };

function hasStringKeyA(data: any): data is { a: string } {
    return typeof data.a === 'string';
}

if (hasStringKeyA(data)) {
    console.log(data.a);
}

但是当我需要检查更多键时,这会变得一团糟:

if (hasStringKeyA(data) && hasStringKeyB(data)) {
    console.log([ data.a, data.b ].join(', '));
}

我想做什么:

if (hasStringKeys(data, ['a', 'b', 'c'])) {
    console.log([ data.a, data.c, data.b ].join(', '));
}

但我不知道如何编写一个可以通过这种方式参数化的类型保护函数。这是一个失败的糟糕尝试:

function hasStringKeys <K extends string[]> (data: any, keys: Keys): data is { [ k: typeof K ]: string } {
    for (const key of keys) {
        if (typeof data[key] !== 'string') {
            return false;
        }
    }
    return true;
}

这可能吗?怎么样?

【问题讨论】:

    标签: typescript typeguards


    【解决方案1】:

    你很接近。我将使用类型参数来捕获项目的字符串文字类型,而不是整个字符串数组。而且您需要使用映射类型而不是索引签名,您可以自己编写 ({ [ k in K ]: string }) 但预定义的 Record 类型也应该可以工作:

    const data: object = { a: 'one', b: 'two', c: 'three' };
    
    if (hasStringKeys(data, ['a', 'b', 'c'])) {
        console.log([ data.a, data.c, data.b ].join(', '));
    }
    
    function hasStringKeys <K extends string> (data: any, keys: K[]): data is Record<K, string> {
        for (const key of keys) {
            if (typeof data[key] !== 'string') {
                return false;
            }
        }
        return true;
    }
    

    Playground Link

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-27
      • 1970-01-01
      • 2019-03-02
      • 2022-01-26
      • 2019-02-10
      • 1970-01-01
      • 2018-12-03
      • 2017-06-06
      相关资源
      最近更新 更多