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