Tag Archives: refactoring

I recently covered an easy way to silence TypeScript when dealing with 3rd party libries with missing or incorrect types.

An additional question that post brought up was:

How do I get fix TypeScript "namespace has no exported member" errors?

The problem

Let's say you're using the popular JavaScript game framework Phaser, which has multiple complex deeply nested objects. The types provided are virtually always out of date with the library itself since Phaser is complex, quickly moving and mostly used by people writing JS rather than TS.

With an existing TypeScript project, if you've been updating your types as you go, there's no issue. But when you migrate a project from JS to TS, you'll have a lot of errors to work through. Even a new project on the newest version of the framework can be an editor full of red squiggly lines and type errors.

Worse still places in your code must refer to members of Phaser. Even if you write declare const Phaser: any; at the top of your app to silence all TS errors from importing or using Phaser, you've still got two problems. First, it's overkill and you probably do want to get your app typed, including the Phaser portions at some point. Second, you're probably going to make your own class which has a member of type Phaser.Game. Since Phaser.Game is also very complex and generally ships with incomplete or out of date types, you'll end up with with the "namespace has no exported member error".

The solution

Work from the outside of your 3rd party library in. Disable warnings on member types by exporting their types in the 3rd party library's namespace.

namespace Phaser {
  export type Game = any;
}

export class MyGame {
    private actors: Array<MyActorType>; 
    private actor: <MyActorType>;
    protected game: Phaser.Game;  // TS errors are silenced here now!
    protected manageAssets(): void { };
    // ... the rest of the MyGame class
}

Now, you'll no longer get the error about Phaser.Game. In other modules, where you use members of Game, you can dig deeper with the same process if there are further nested type issues. Eventually you'll get down to simple objects that are trivial to correctly type.

Fixing these issues as you go, you'll get to a point where all the parts in of the 3rd party library that are used in your app will be correctly typed and the others will be silenced. This is a reasonable trade-off with a large 3rd party library in flux, such as Phaser or Materialize.