将 class 添加到现有模块(外部库)

Add class to existing modules (external library)

我正在尝试通过添加新的 Phaser.Physics.Box2D 模块来扩展 Phaser。 Phaser 内部已经使用了这个模块,但它是一个额外的插件,我想定义我自己的

我正在为我的项目使用 TypeScript。我想用它来以正确的方式扩展移相器。我发现 this issue 解释了如何添加新定义(接口),但没有关于添加代码(实现)的内容。

这是我尝试过的方法(我也尝试过很多变体)。

// This is part of phaser typescript definitions
// The code I try to add is at the end.
// You can test it on https://www.typescriptlang.org/play/index.html
declare module "phaser-ce" {
    export = Phaser;
}

declare class Phaser {
    static VERSION: string;
    static DEV_VERSION: string;
    static GAMES: Phaser.Game[];
}

declare module Phaser {
    enum blendModes {

        NORMAL,
        ADD,
        MULTIPLY,
        SCREEN,
        OVERLAY,

    }

    class Animation {
        onComplete: Phaser.Signal;
        reverse(): Animation;
        // More of course ...
    }


    class Signal {
        active: boolean;
        // More of course ...
    }

    class Game {
        constructor(width?: number | string, height?: number | string, renderer?: number, parent?: any, state?: any, transparent?: boolean, antialias?: boolean, physicsConfig?: any);
        context: CanvasRenderingContext2D;
        // More of course ...
    }

    class Physics {

        constructor(game: Phaser.Game, config?: any);

        static ARCADE: number;
        static P2JS: number;
        static NINJA: number;
        static BOX2D: number;
        static CHIPMUNK: number;
        static MATTERJS: number;

        arcade: Phaser.Physics.Arcade;
        config: any;
        game: Phaser.Game;
        ninja: Phaser.Physics.Ninja;
        p2: Phaser.Physics.P2;
        box2d: any; // Id like to override this, if you have any good idea I take it :p

    }

    module Physics {

        class Arcade {

        }

        class Ninja {

        }

        class P2 {

        }


        module P2 {

            class Body {

                static DYNAMIC: number;
                static STATIC: number;
                static KINEMATIC: number;
            }
        }
    }
}


// I want to add this class to the Physics module...
class MyAwesomeWork {
    constructor(hello: string) {
        console.log(hello);
    }
}

declare module Phaser {
    module Physics {
        class Box2D {

        }
        module Box2D {
            // ... But this fails :(
            class Body {

            }
        }
    }
}

Phaser.Physics.Box2D = MyAwesomeWork;

您不应该直接修改或扩展外部包,因为如果模块更新,那么您添加的代码将被重写。不幸的是,直接修改库是不可能的。

大多数开发人员解决这个问题的方法是在他们的源代码中编写他们自己的扩充和包装器。这样,您拥有的这个自定义 class 就不会被新的 npm install 重写。

这不是 TypeScript 独有的,JavaScript 也是如此。你可以自己增加类型的唯一原因是因为并不是所有的包都是有类型的,为了静态类型,TS 假设你知道得更多。此外,这些类型不在编译代码中,因此修改它们对最终产品没有影响。但是,对于实际的可执行代码,TS 和 JS 假定库作者是正确的,迫使您将自己的更改放入您自己的代码库中。

这是解决方案

import 'phaser-ce';

declare global {
    module Phaser {
        module Physics {
            class Box2D {
                prop: number;
                // Constructor declaration matters
                constructor(param: WhateverType);
            }
        }
    }
}

Phaser.Physics.Box2D = class {
    public prop = 42;
    constructor(private param: WhateverType) {}
};