首页 > 解决方案 > 测试缺少的接口属性

问题描述

我想检查一个对象是否实现了给定接口的所有属性。因为 TS 中的接口只是编译时构造,所以我需要列出所有要在运行时检查的属性。我使用了这个答案:https ://stackoverflow.com/a/60932900/10061195创建以下代码:

interface Test {
    a: number,
    b: number,
}

type CheckMissing<T extends readonly any[], U extends Record<string, any>> = {
    [K in keyof U]: K extends T[number] ? never : K
}[keyof U] extends never ? T : T & "Error: missing keys"

type CheckDuplicate<T extends readonly any[]> = {
    [P1 in keyof T]: "_flag_" extends
    { [P2 in keyof T]: P2 extends P1 ? never :
        T[P2] extends T[P1] ? "_flag_" : never }[keyof T] ?
    [T[P1], "Error: duplicate"] : T[P1]
}

// throw an error if the given object does not have all the properties of the given interface
function checkInterface<I, S extends (keyof I)[]>(val: any, keys: S & CheckMissing<S, I> & CheckDuplicate<S>): val is I {
    const missing = keys.filter(k => val[k] === undefined);

    if (missing.length > 0) {
        throw new Error(`Missing properties: ${missing}`);
    }

    return true;
}

let val: unknown = { a: 5, b: 7 };

// ensure that the object val is of type Test
if (checkInterface<Test, ["a", "b"]>(val, ["a", "b"])) {
    console.log(val.a);
}

它完全符合我的要求,除了我需要指定属性列表两次(一次作为模板参数,一次作为参数)。有没有办法只提供一次列表?

我尝试删除参数中的列表,但之后似乎无法从模板参数中检索列表。如果我删除模板参数,我将无法强制执行CheckDuplicateand类型。CheckMissing

标签: typescripttemplatestypescript-genericstypeguards

解决方案


推荐阅读