override/redeclare 一个 class 带有打字稿中的泛型

override/redeclare a class with generics in typescript

目前我正在使用三个 js 和 typescript 开发一个项目。我发现出于分组目的,GroupGroup class is recommended. Unfortunately the type definitions 没有像这样的通用

meshGroup = new Group<Mesh>() 

其中 meshGroup.children 属性 仅包含 Meshes

我试过了

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

meshGroup = new MeshGroup() 

但出现此控制台错误

_classes_MeshGroup__WEBPACK_IMPORTED_MODULE_16__.MeshGroup is not a constructor

我查了一下是否有一种简单的方法可以在打字稿中实现这种简单的包装器,但没有成功。

我的另一个解决方案是实现

的类型化数组
meshGroup: Mesh[] = []

并使其与 class 保持同步以处理类型,但它增加了另一层处理同步。

由于我不是 typescript 的专家,是否有快速的类型定义技巧来实现这个“包装器”-定义?

当您调用 group.children 时,您会得到一个数组 Object3D[] as per the definition file。这是因为 Group 可以在其中包含其他 Group, Sprite, Line, Point, Mesh, etc.,因此它默认为通用 Object3D。但是,如果您确定它只会包含 Meshes,您可以简单地用以下命令轻推它:

const group: THREE.Group = new THREE.Group();
const children = group.children as THREE.Mesh[];

// Now we can access Mesh attributes, like
const mat = children[0].material;

编辑

它也有点可能扩展 Group class 更多 type-safer class 并调用父函数 (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
  }
}

我的initial/old回答

感谢您的回答

这无疑是一个解决方案。目前我想出了另一种方法,通过 patch-package 覆盖包并像这样编辑 Group.d.ts 文件:

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;
}

除了你的回答,我还得到了 type-safety 对我来说也很重要的方法!

我不知道这是否最适合我未来的需求,但目前这解决了我的 type-addiction :D