在运行时分析类型或接口,并将一些逻辑应用于其成员

时间:2019-11-14 20:31:31

标签: typescript

我有以下方法:

    protected async process(request: express.Request, response: ApiResponse, params: Request_Token, body: void) {

        if (!params.unitId)
            throw new ApiException(400, "Missing unitId");

        if (!params.product)
            throw new ApiException(400, "Missing product");

        const token = ...

        return token;
    }

这些if行仅在使用不同类型的情况下才与每个api调用重复。.现在我找不到一种在类型属性上进行迭代的方法..我真的很希望能够做到这一点。这样可以节省很多代码!

有什么想法...?

1 个答案:

答案 0 :(得分:1)

这不可能直接实现,因为在编译Typescript代码时,类型(包括接口)不会在生成的Javascript代码中表示。 Javascript代码不可能在运行时访问它们,因为它们根本不存在于Javascript代码中。

// no Javascript generated
interface A { x: string, y: number, z: boolean }
type B = { p: number, q: number };

但是,有一种解决方法,可以通过创建具有正确属性类型的const对象,然后将接口定义为typeof该对象:

// Javascript generated
const _A_prototype = { x: '', y: 0, z: false };
type A = typeof _A_prototype;

const _B_prototype = { p: 0, q: 0 };
type B = typeof _B_prototype;

然后_A_prototype_B_prototype的代码在运行时可用,因此可以动态检查其属性:

function assertType<T>(a: any, prototype: T): asserts a is T {
    for (let k in prototype) {
        if (!(k in a)) {
            throw new Error('Missing property ' + k);
        } else if (typeof a[k] !== typeof prototype[k]) {
            throw new Error('Wrong property type for ' + k);
        }
    }
}

用法:

let a: any = { x: 'hi', y: 14, z: true };
assertType(a, _A_prototype);

a; // inferred as { x: string, y: number, z: boolean }

缺点是您的IDE对a的类型提示将是{ x: string, y: number, z: boolean },而不仅仅是A

Playground Link