Interface Type Check with Typescript

Interface type check with Typescript

You can achieve what you want without the instanceof keyword as you can write custom type guards now:

interface A {
member: string;
}

function instanceOfA(object: any): object is A {
return 'member' in object;
}

var a: any = {member: "foobar"};

if (instanceOfA(a)) {
alert(a.member);
}

Lots of Members

If you need to check a lot of members to determine whether an object matches your type, you could instead add a discriminator. The below is the most basic example, and requires you to manage your own discriminators... you'd need to get deeper into the patterns to ensure you avoid duplicate discriminators.

interface A {
discriminator: 'I-AM-A';
member: string;
}

function instanceOfA(object: any): object is A {
return object.discriminator === 'I-AM-A';
}

var a: any = {discriminator: 'I-AM-A', member: "foobar"};

if (instanceOfA(a)) {
alert(a.member);
}

Typescript: How to check interface type

Interfaces in Typescript just syntatic sugar for your ide. It is unpossible to check interface types like in other languages. Knowing in C# for example.

But with type guard you can recognize which interface are in use.

interface ReadOnlyInfo {
itemId: string;
....
}

interface EditInfo {
formId: number;
....
}

function getUniqueId (info: ReadOnlyInfo | EditInfo) {
if (isReadOnlyInfo(info)) return info.itemId;
if (isEditInfo(info)) return info.formId;
}

function isReadOnlyInfo(item: any): item is ReadOnlyInfo {
return 'itemId' in item;
}

function isEditInfo(item: any): item is EditInfo {
return 'formId' in item;
}

On this way you get a better ide support

instanceof check on interface

There is no way to runtime check an interface as type information is not translated in any way to the compiled JavaScript code.

You can check for a specific property or a method and decide what to do.

module MyModule {
export interface IMyInterface {
name: string;
age: number;
}
export interface IMyInterfaceA extends IMyInterface {
isWindowsUser: boolean;
}
export interface IMyInterfaceB extends IMyInterface {

}

export function doSomething(myValue: IMyInterface){
// check for property
if (myValue.hasOwnProperty('isWindowsUser')) {
// do something cool
}
}
}

Check if an object implements an interface at runtime with TypeScript

No.

Currently, types are used only during development and compile time.
The type information is not translated in any way to the compiled
JavaScript code.

From https://stackoverflow.com/a/16016688/318557, as pointed out by @JasonEvans

There is an open issue since Jun 2015 about this in the TypeScript repo: https://github.com/microsoft/TypeScript/issues/3628

How to check custom interface type in Typescript

Update: the question as stated doesn't indicate that the request is to be able to distinguish the type without checking properties. Unfortunately, that is impossible; TypeScript compiles to JavaScript, which is what actually runs. And TypeScript's type system, where interfaces like A and B are found, is completely erased when the code is compiled. So there is no A or B at runtime to check.

If you want to be able to distinguish, at runtime, whether myObj is A or B, you need to write JavaScript code that does this... such as checking properties. What you can do is use TypeScript to help you write this code and give it typings so that the compiler also understands that your property check narrows an A | B to an A or a B. And that's what the rest of this answer (and the other question's answer) tells you. Good luck!


The other question's answer suggests that you write a user-defined type guard function, which will definitely work; the idea is that you tell the compiler what you consider to be a good way to distinguish between A and B, and it will let you use that function to do so.

An easier way to do it in your case is to use the in operator, which can be used as a type guard (since TypeScript 2.7). For example:

declare const obj: A | B;
if ("b_id" in obj) {
// obj is a B in here
console.log(obj.name.toUpperCase());
} else {
// obj is an A in here
console.log(obj.a_id.toUpperCase());
}

Note that this is technically unsafe, since it's possible to have an object of type A | B which isn't distinguishable that way:

function getEvilAorB(): A | B {
interface EvilA extends A {
b_id: number;
}
const evilA: EvilA = { name: "", a_id: "", b_id: 123 };
return evilA; // okay, EvilA extends A extends A | B
}

Notice that getEvilAorB() returns a valid A, which is therefore a valid A | B, but unfortunately it will fail the above test because of the numeric name property:

const evilA = getEvilAorB();
if ("b_id" in evilA) {
console.log(evilA.b_id.toUpperCase()); // compiles but at runtime
// TypeError! evilA.name.toUpperCase is not a function
}

If you aren't concerned about such edge cases, then the in type guard is probably sufficient. Otherwise you should consider either writing a user-defined type guard, or making your interfaces members of a discriminated union which is a conventional and supported way to have the compiler distinguish between union members.

Hope that helps; good luck!

Playground link to code



Related Topics



Leave a reply



Submit