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, 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
}
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)
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.
Do you mean rewriting the 3rd party library's definition file or creating an additional one?
Yes. These definitions aren't actually part of the 3rd party library anyway, but they are developed separately at definitelytyped.org for example.
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?
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.