Search code examples
javascripttypescriptclassprototype

javascript to typescript: mix prototype based object with class based one


i'm trying to mix javascript prototype with class based, like this:

function Cat(name) {
    this.name = name;
}
Cat.prototype.purr = function(){
    console.log(`${this.name} purr`);
}
Cat.prototype.meow = function(){
    console.log(`${this.name} meow`);
}


class Tiger extends Cat {
    constructor(name) {
        super(name);
    }

    meow() {
        console.log(`${this.name} roar`);
    }
}

the JS code above is valid. then I convert the code to typescript like this:

function Cat(this : any, name : string) {
    this.name = name;
}
Cat.prototype.purr = function(){
    console.log(`${this.name} purr`);
}
Cat.prototype.meow = function(){
    console.log(`${this.name} meow`);
}


// error: Type '(this: any, name: string) => void' is not a constructor function type.
class Tiger extends Cat {
    constructor(name : string) {
        super(name);
    }

    meow() {
        console.log(`${this.name} roar`);
    }
}

the class Tiger doesn't accept the class Cat as its base class. (valid in JS but not in TS). I cannot change the Cat to standard class syntax because I need the .prototype access to be pointed to another JS library.

anyone can fix the TS code above? maybe add some .d.ts definition.

Note: adding // @ts-ignore works but I cannot do that because the VS-code intellisense will not work.


Solution

  • Well, you could attempt to do something like this

    interface CatClass {
      name: string
      purr(): void
      meow(): void
    
      new (name: string): CatClass
    }
    
    const Cat = function(this: CatClass, name: string) {
      this.name = name
    } as unknown as CatClass
    // Then add functions to prototype and everything should be fine
    

    The question is why you are doing this in the first place, why not rewriting it as a normal class? There doesn't seem to be any info about how to type such function classes without this as unknown as CatClass thing (which seems like a little hack but well), maybe because no one has ever needed to do this, which I understand. Anyway after transpilation all classes become functions