Search code examples
typescriptthree.jsdecoratorwrapper

override/redeclare a class with generics in typescript


currently i am working on a project using three js and typescript. I have found out that for grouping purposes the Group class is recommended. Unfortunately the type definitions of Group dont come with a generic like this

meshGroup = new Group<Mesh>() 

of where the meshGroup.children property only consists of Meshes

i tried this

declare class MeshGroup extends Group {
  children: Mesh[]
  add(...object: Mesh[]): this
}

meshGroup = new MeshGroup() 

but got this console error

_classes_MeshGroup__WEBPACK_IMPORTED_MODULE_16__.MeshGroup is not a constructor

I looked up if theres an easy way to implement such simple wrapper in typescript but with no success.

My other solution would be to implement an typed array of

meshGroup: Mesh[] = []

and keep it in sync with the class to handle the types but it adds another layer of handling the sync.

Since i am not a pro at using typescript, is there a quick type definition trick to implement this "wrapper"-Definition?


Solution

  • EDIT

    Its also kinda possible extending the Group class with a more type-safer class and calling the parent functions (decorator pattern):

    
    import { Group } from 'three'
    import { Object3D } from 'three/src/core/Object3D'
    
    export default class TypedGroup<T extends Object3D = Object3D> extends Group {
      children: T[] = []
    
      add(...object: T[]) {
        return super.add(...object)
      }
    
      remove(...object: T[]): this {
        return super.remove(...object)
      }
    
      attach(object: T): this {
        return super.attach(object)
      }
    
      getObjectById(id: number): T | undefined {
        return super.getObjectById(id) as T | undefined
      }
    
      getObjectByName(name: string): T | undefined {
        return super.getObjectByName(name) as T | undefined
      }
    
      getObjectByProperty(name: string, value: string): T | undefined {
        return super.getObjectByProperty(name, value) as T | undefined
      }
    }
    
    

    my initial/old answer

    Thanks for the answer @Marquizzo!

    That defenitely could be a solution. Currently i came up with another way with overriding the package via patch-package and edit the Group.d.ts file like this:

    export class Group<T extends Object3D = Object3D> extends Object3D {
        constructor();
        type: 'Group';
        readonly isGroup: true;
        children: T[];
        add(...object: T[]): this;
        remove(...object: T[]): this;
        attach(object: T): this;
        getObjectById(id: number): T | undefined;
        getObjectByName(name: string): T | undefined;
        getObjectByProperty(name: string, value: string): T | undefined;
    }
    

    In addition to your answer i also get type-safety on the methods which was important to me too!

    I dont know if this fits the best for my needs in the future but currently this solves my type-addiction :D