Greg Wozniak
Greg Wozniak

Reputation: 7172

Using external abstract class in Typescript without extending it

I've got one module called utils.tsx so that:

interface IUtils {
    toUri: (route: string) => string
}

export default abstract class Utils implements IUtils {
    public toUri = (route: string) => {
        return route
    }
}

and another file where I wish to use this utils module:

 import Utils from '../helpers/utils'

 class Router  {
     private getBuilder = (search: string) => {
       const path = Utils.toUri(search)
     }
 }

When I am trying to use Utils.toUri I am getting TS error:

[ts] Property 'toUri' does not exist on type 'typeof Utils'.

My intention is to call the external abstract class function without extending the Router class nor inheriting from it (as I will have more than one external module in the main file).

Could someone help me to bypass it and understand?

PS: I tried with public abstract toUri() too. Perhaps I mixed up the routines from other programming languages and confusing usage of static with abstract here...

Upvotes: 1

Views: 379

Answers (1)

jcalz
jcalz

Reputation: 327884

You don't want Utils to implement IUtils, since Utils is the instance type of the class. It looks like you want the Utils constructor (whose type is typeof Utils) to implement IUtils. That is, you want toUri to be a static method of the Utils class. Like this:

abstract class Utils  {
  public static toUri = (route: string) => {
    return route
  }
}

There is no way to annotate the class Utils declaration to say that the static side of the class implements IUtils. Luckily, the Utils constructor will automatically be seen as something that implements IUtils without needing to write implements IUtils anywhere. Thanks, structural typing:

declare function takeIUtils(iUtils: IUtils): void;
takeIUtils(Utils); // works anyway

This should allow your Router class to behave as desired.


Side note, I wonder if you really want Utils to be a class at all. If you never want to see an instance of Utils like class X extends Utils {...}; new X(), then you're probably making life unnecessarily hard for yourself. Maybe it should just be a value:

export const Utils : IUtils = {
  toUri(route: string) {
    return route
  }
}

Or a namespace:

export namespace Utils {
  export function toUri(route: string) {
    return route
  }
}

Or a module, or something.


Anyway, hope that helps. Good luck!

Upvotes: 1

Related Questions