检查对象是否在运行时使用 TypeScript 实现接口

2022-08-30 05:26:49

我在运行时加载一个JSON配置文件,并使用接口来定义其预期结构:

interface EngineConfig {
    pathplanner?: PathPlannerConfig;
    debug?: DebugConfig;
    ...
}

interface PathPlannerConfig {
    nbMaxIter?: number;
    nbIterPerChunk?: number;
    heuristic?: string;
}

interface DebugConfig {
    logLevel?: number;
}

...

这使得访问各种属性变得方便,因为我可以使用自动完成等。

问:有没有办法使用此声明来检查我加载的文件的正确性?即我没有意外的属性?


答案 1

“有”一种方法,但你必须自己实现它。它被称为“用户定义的类型保护”,它看起来像这样:

interface Test {
    prop: number;
}

function isTest(arg: any): arg is Test {
    return arg && arg.prop && typeof(arg.prop) == 'number';
}

当然,该函数的实际实现完全取决于您,但好的部分是它是一个实际的函数,这意味着它是可测试的。isTest

现在,在运行时,您将用于验证对象是否依赖于接口。在编译时,typescript 拾取保护并按预期处理后续用法,即:isTest()

let a:any = { prop: 5 };

a.x; //ok because here a is of type any

if (isTest(a)) {
    a.x; //error because here a is of type Test
}

更深入的解释在这里: https://basarat.gitbook.io/typescript/type-system/typeguard


答案 2

这是另一种选择,专门用于此:

ts-interface-builder 是您在构建时在 TypeScript 文件上运行的工具(例如 )来构建运行时描述符(例如 )。foo.tsfoo-ti.ts

ts 接口检查器使用这些在运行时验证对象。例如:

import {createCheckers} from 'ts-interface-checker';
import fooDesc from 'foo-ti.ts';
const checkers = createCheckers(fooDesc);

checkers.EngineConfig.check(someObject);   // Succeeds or throws an informative error
checkers.PathPlannerConfig.check(someObject);

可以使用方法来确保没有未知属性。strictCheck()