Update 10/6: the TypeScript folks are listening and it sounds like this will be fixed in the next release. There’s a recent issue to track as well.
At Ionic, we’ve gone all-in on TypeScript. In fact, GitHub says we’re the most starred TypeScript project on planet earth. We initially came to TypeScript because the Angular team was building v2 in TS and it sounded interesting, but we’ve stayed with it because we think it’s one of the best ways to write modern JavaScript.
For me personally, the dream of TypeScript was always that I could improve my JavaScript by adding typings as I saw fit. In that sense, my JS would be strengthened with additional type checking as I went along, but the plain JS code would work as if nothing changed. On top of that, I could seamlessly import any JavaScript module regardless of whether it used TypeScript. If I wanted to, I could build the whole app with rigorous type checking from the start, but that was an optional way of using the language and certainly not required.
TypeScript is among the rare language projects of history that have seen significant adoption from developers, an incredible feat to be sure. However, TypeScript adoption will always pale in comparison to JavaScript adoption in general. In that sense, I believe it is crucial that TypeScript plays naturally with other JavaScript that is not typed and is not written in TypeScript. After all, TypeScript is a superset of JavaScript, right?
That brings me to what we’ve seen over the last year of Ionic 2 development with TypeScript. Right now, the number one challenge Ionic developers face when using TypeScript in Ionic 2 is importing JavaScript modules from npm that are not typed and do not have typings available. Over and over, we see developers attempt to follow code they find on the web where an ES6+ library is imported, but then struggle to understand why TypeScript then throws errors that the module cannot be found.
The workaround for this in TS 2.0 is to add a stub module declaration, something like
declare module “module-from-npm”;
And place this in a d.ts file. As such, we’re seeing developers that have TypeScript savvy add a bunch of these stub definitions that have no type information, just to get TypeScript to not throw errors on compilation for modules that don’t and might never have type information available.
The argument for requiring types for modules is that TypeScript can’t tell what the “shape” of the module is without types. However, it shouldn’t need to know the shape because the module doesn’t have nor does it need types. Yes, this means my IDE/intellisense experience will suffer, but that’s okay. If I want to add typings for the module later, and perhaps contribute them to the @types registry, why not let me do that once I’m ready to enhance my experience through typings?
In the past, I’ve gone so far as to fork existing libraries on github just to add typing stubs so that users won’t have to add them in their own apps, because I know that being a user of a module without types available can be incredibly frustrating:
I believe the best way forward from this issue is to support a compiler flag, perhaps allowImplicitAnyModules, that automatically treats untyped imports as if they had a corresponding declare module definition stub. I know we’d absolutely enable that by default for Ionic apps, and it sounds like many on the issue linked above would like a similar feature.
My goal with this post is to appeal to the TypeScript team that being more forgiving about untyped modules would make TypeScript considerably easier to use and to incorporate into existing JS projects. Additionally, it would, in my opinion, better serve the dream of TypeScript being a typed superset of JavaScript. That JS modules don’t import today without types is a fundamental break in the idea that TypeScript is just JavaScript with some extra goodies. Finally, this would let me use TypeScript for my project, while not forcing it on the libraries of others, many of which are passionate about being purely ES6/7 libraries and have no interest in adding typings for a non-standard superset of the language.
I believe this would help TypeScript proliferate and lower the barrier to entry for newcomers to modern JavaScript and to typed JavaScript. I know Ionic developers would sure be happy about this!