Typescript check generic type for interface

Gargoyle picture Gargoyle · Jul 19, 2018 · Viewed 11k times · Source

In my angular 6 file I've got an interface defined and then in a method that takes a generic parameter, T, I want to determine if T implements that interface at runtime. Is that possible?

I tried to do if (T instanceof INetworkObject) but the compiler doesn't like that.

export interface INetworkObject {
    fixNetworkObject(): void;
}

protected getTypedItem<T>(endpoint: string, C: { new(): T }): Observable<T> {
    return this.http.get<T>(`${this.baseUrl}/${endpoint}`)
        .pipe(map(element => {
            if (!element) {
                return null;
            }

            const ret = Object.assign(new C(), element);

            if (T.type instanceof NetworkObject) {

            }

            // This ugliness is what I'm doing now
            if (typeof ret['fixNetworkObject'] === 'function') {
                ret['fixNetworkObject']();
            }

Basically what I'm trying to do is call fixNetworkObject on ret if it implements that interface.

Answer

morsecodist picture morsecodist · Jul 19, 2018

Unfortunately, you can't use instanceof because interfaces don't exist at runtime. You need to declare a type guard like so (see the Advanced Types Documentation):

function isINetworkObject(obj: any): obj is INetworkObject {
  return typeof ret.fixNetworkObject === 'function';
}

Then modify your if:

if (isINetworkObkect(ret)) {
  ret.fixNetworkObject();
}