Dolf Andringa
Dolf Andringa

Reputation: 2170

type check with typescript interface inheritance

I have an interface and two interfaces that extend it:

interface Layer {
    name: string;
    pretty_name: string;
}

interface SubLayer extends Layer{
    url: string;
}

interface AnotherLayer extends Layer{
    file: string;
}

Then I a service I have function that handles any Layer argument, and then needs to distinguish between the sub-interfaces and call the correct functions according:

class LayerDataService {

    static getLayer(layer: Layer) {
        if (......) {
            return LayerDataService.getSubLayer(layer as SubLayer );
        }
        else if (......) {
            return LayerDataService.getAnotherLayer(layer as AnotherLayer);
        }
    }

    static getAnotherLayer (layer: AnotherLayer) {

    }
    static getSubLayer(layer: SubLayer) {

    }
}

So on the ..... there I want to distinguish between layers which implement SubLayer and layers implementing AnotherLayer.

So I know I can't use instanceof, because they aren't classes, they're objects implementing interfaces. But is there a way that doesn't involve manually checking each-and-every attribute manually like I can do in type guards?

Upvotes: 0

Views: 1680

Answers (2)

Matthew Layton
Matthew Layton

Reputation: 42229

Since interfaces are erased at compile time, there's no runtime information about them, hence no instanceof. The only solution I can think of is to invert the dependency, so it's the layer that decides how it's called...

class LayerDataService {
    static getLayer(layer: Layer) {
        layer.get(this);
    }
}

interface Layer {
    name: string;
    pretty_name: string;
    
    get(service: LayerDataService): void;
}

interface SubLayer extends Layer{
    url: string;
}

interface AnotherLayer extends Layer{
    file: string;
}

This way each implementation is responsible for calling the relevant function on the LayerDataService, which admittedly adds overhead. I'm not entirely sure whether this would work in your case, but I thought worth mentioning.

Upvotes: 1

Marek Urbanowicz
Marek Urbanowicz

Reputation: 13634

Not sure if I understand correctly, but you can possibly use type guard function I think.

function (layer: unknown): layer is AnotherLayer {
   return !!layer.file;
}

Do the same for SubLayer, then you can use it as standard function but inside the parenthesis you will have it strongly typed as the specified type.

Upvotes: 0

Related Questions