DEV Community

Mark
Mark

Posted on • Originally published at logicmason.com on

TypeScript libraries with incorrectly typed members

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?

TypeScript 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, parts 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
}
Enter fullscreen mode Exit fullscreen mode

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.

Subscribe to more content from logicmason.com

Top comments (5)

Collapse
 
thorstenhirsch profile image
Thorsten Hirsch

You can also write definition files (.d.ts) as described in the typescript documentation. That way you don't clutter your own files with definitions of 3rd party libraries.

Collapse
 
logicmason profile image
Mark

Do you mean rewriting the 3rd party library's definition file or creating an additional one?

Collapse
 
thorstenhirsch profile image
Thorsten Hirsch

Yes. These definitions aren't actually part of the 3rd party library anyway, but they are developed separately at definitelytyped.org for example.

Thread Thread
 
logicmason profile image
Mark • Edited

Right, I'm familiar with definitelytyped (though they don't have typings for the framework mentioned in this post).

By "yes" do you mean writing a supplementary definitions file or do you mean editing the one pulled from definitelytyped?

Thread Thread
 
thorstenhirsch profile image
Thorsten Hirsch

Well, I hope every TS developer is joining the effort to provide definition files for everything at central repositories like definitelytyped. So I always start looking there for an existing one and update it if necessary. If none exists I write it myself... and send it to definitelytyped when it's complete and tested successfully.

Supplementary files are a bad idea. Are people really that afraid of pull requests? Withholding fixes does not only thwart the idea of open source, but it's also a technical debt in a project. Major upgrades of 3rd party libraries can already be a pain, but they're even worse if you need to upgrade your private fixes for the 3rd party libraries, too.