0

I have the following method:

    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;
    }

These if lines are duplicated with every api call only using different types.. now I didn't find a way to iterate on types properties.. and I would really like to be able to do that.. it would save me a LOT of code!!

Thoughts...?

TacB0sS
  • 10,106
  • 12
  • 75
  • 118

1 Answers1

1

This isn't possible directly, because when Typescript code is compiled, types (including interfaces) are not represented in the resulting Javascript code. It would be impossible for the Javascript code to access them at runtime since they simply aren't present in the Javascript code at all.

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

However, there is a way around this by creating a const object with the right property types, and then defining the interface as typeof that object:

// 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;

The code for _A_prototype and _B_prototype is then available at runtime, so their properties can be checked dynamically:

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);
        }
    }
}

Usage:

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

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

The downside is your IDE's type-hint for a will be { x: string, y: number, z: boolean } instead of just A.

Playground Link

kaya3
  • 47,440
  • 4
  • 68
  • 97