Posts about TypeScript
Since JavaScript is not a strongly typed language, it doesn't support function overloading. However, you might not be aware that TypeScript provides limited support for function overloading on top of existing JavaScript syntax. Still, it might make your functions easier to use from client code in certain scenarios.
In my previous blog post I explained how the keyof type operator in TypeScript can sometimes be used as a replacement for parameters passed by reference which aren't supported in JavaScript. Let's try to restrict the parameter to only allow names of members of a specific type.
In TypeScript, there is no way to pass a variable to a method by reference so that the method could both read its value and write a new value to it. For class fields, such functionality can be achieved to some extent by passing the field name to the method while still preserving type safety.
I have already written about union types in TypeScript in the past and explained how generic functions can be used with any underlying type and still preserve the original type as their return value. However, unless you're using the latest minor version of TypeScript (5.2 or later), this will not work for array operations on a common union type field.
Recently, I've been adding some GraphQL queries to a legacy web application in TypeScript. With GraphQL, you quickly end up with a lot of similar types, since the query determines which fields are present in a type. I was relying on the TypeScript compiler to warn me of resulting potential type incompatibilities, and was surprised when it quietly allowed a lambda with a subtype parameter.
The TypeScript compiler prevents type-related errors in code, but sometimes it also prevents you from writing perfectly valid JavaScript code. At least, that's how it seems.
Although Blazor makes it possible to develop single-page applications in C# instead of JavaScript or TypeScript, there are still cases where you need to call JavaScript code to accomplish something, such as calling browser APIs or interacting with existing JavaScript libraries. This is called JavaScript interoperability and is well documented. However, it does not mention how you can use Typescript instead of JavaScript.
The type checking provided by the TypeScript compiler is a great tool when working with JavaScript. Even more so when dealing with large, long-lived projects with many developers. Still, sometimes it can fail to warn you about a type error.
In Ionic 6, component events have well-documented, strongly typed arguments. Unfortunately, the outputs in Angular are still typed as Event. The issue has already been reported and there is even a fix for it, but it did not make it into Ionic 6 as it would involve a breaking change. So until the fix is released, you'll have to settle for one of the workarounds.
Type checking in TypeScript helps you ensure that your code is correct and behaves as expected. However, in certain scenarios, it seems more difficult to write such code than plain JavaScript, especially if you are not familiar with all the language constructs available to you in TypeScript. Functions that support arguments of multiple types can be one such case.
Type checking in Angular is constantly improving. In newer versions, it even does a good job in templates. This can help us detect errors in our code earlier. However, sometimes extra work is needed to take full advantage of this feature.
The ng-template element in Angular allows you to reuse parts of a component template, which in a sense makes it a lightweight subcomponent. By default, its context is not typed, but it can be made strongly typed with a little trick.
Cloning arrays in JavaScript is a topic I get asked about regularly by other team members. This post is intended as a reference that I can refer to on similar occasions in the future.
Type coercion is the term used for automatic conversion between data types in JavaScript. If you're not careful, it can be a cause for subtle bugs in your code. This post is dedicated to one such example I recently encountered.
Due to the dynamic nature of JavaScript, some libraries encourage you to extend their default types. An example of that is Vue.js. Its plugins often extend the Vue prototype that's available in every component. How can this best be handled with TypeScript?
If you want to share your Vue.js components across multiple projects, you would typically package them into a component library. However, the people behind the Bit platform propose that distributing each component as a separate package is a better approach. I decided to try implementing a basic solution for per-component packaging myself to see what it would take to get it working.
Although Vue CLI has built-in support for building component libraries, there's still some work in creating one, especially if you want it to be TypeScript and SSR compatible.
Storybook is a great tool for component development. But although it supports many frameworks, it still sometimes gives the appearance of being React-first. For example, the default configuration for Vue.js doesn't have TypeScript support.
I was recently invited to look at a piece of seemingly working JavaScript code. The problem was that the TypeScript compiler was complaining about it after it was annotated with type information. In the end, these errors uncovered a hidden bug in the code.
Vuex store code can be quite verbose, especially with wrappers for type-safety in TypeScript. A lot of that plumbing can be avoided with the vuex-module-decoorators package. There's some extra configuration required to get it working in NuxtJS.
Even if you select TypeScript and Jest support when creating a new NuxtJS project, it still isn't fully configured for writing tests in TypeScript, let alone for testing components written with JSX syntax. This post describes my journey to a working configuration.
Although both Vue.js and NuxtJS have TypeScript support, it often seems incomplete. For example, there's no compile-time type checking in Vue.js templates. Any errors will only be reported at runtime. Currently, the only way to achieve compile-time type safety is to use render functions with JSX syntax instead.
String literal types are a lightweight alternative to string enums. With the introduction of the const assertions in TypeScript 3.4, even type guards can be implemented in a DRY manner.
TypeScript was designed to formally describe types in any JavaScript code. Because of this, its type system supports much more than a type system of a typical objected oriented language does. Let's say I want to create a type that consists of a subset of members of another type. There are multiple ways how to achieve that.
As one could expect based on the title of the book, all of the code samples are written in TypeScript. However, the concepts presented are more generally applicable and not language specific. I would recommend the book to any developer who can fluently read JavaScript/TypeScript (or any other C-based language).
I've been doing some Cordova plugin development recently and at some point, I've decided to add TypeScript type declarations to make the plugin easier to consume from Ionic (or other TypeScript based) applications.
I have a hard time recommending the book to anyone. Although it mostly focuses on basics, I don't think it's suitable for beginners because of how short the explanations are. For me, its value was mostly in a few random nuggets of knowledge I stumbled upon while reading.
Recently, we discussed the behavior of Promise.finally in our development team. Even after reading the official documentation, we weren't unanimous on what will happen in certain cases. In the end, I wrote a couple of test cases to make sure about it.
In Ionic 4, even for lazy-loaded modal pages the component must be specified using the type. There's nothing wrong with that. Enforcing strong typing is usually a good idea. However, it can potentially cause a circular dependency, especially if you move the code for creating and opening modal pages to a separate service to avoid repeating the same boilerplate code and make testing easier.
JavaScript prototype inheritance offers much greater flexibility than regular inheritance in object-oriented programming. For example, when extending a class, it allows you to change the method signature. However, when using TypeScript, it's not as easy.
I often need to quickly test some JavaScript or TypeScript code, be it for a blog post or otherwise. Recently, I started using Jest for that because it's so simple to set up. For basic JavaScript code, it's enough to install the npm package. Although Jest doesn't have built-in support for TypeScript, it's almost just as easy to use with the help of ts-jest.
The TypeScript's type system can provide strong typing for many inconvenient situations we might encounter with JavaScript development. For example, union types are great for working with types that are very similar to each other.
I've written about TypeScript imports on my blog before, but as I recently learned, I haven't covered all the cases. The type definitions for the Google Maps JavaScript API contain no modules, only a namespace. Therefore, they can't be imported using the standard import directive. I was stuck until I found an excellent resource on Stack Overflow.
In JavaScript, it's really easy to just add another field to an existing object. Of course, there is a way to express that in TypeScript. Actually, there's even more than one way to do it.
JavaScript has always supported functions with variable number of arguments, although the syntax required some getting used to. In TypeScript and ECMAScript 6 rest parameters and spread syntax provide a more convenient alternative that also works with arrow functions.
RxJS used to encourage monkey patching of operators and helper functions onto the Observable object. However, this has an unfortunate side effect of making the imports available everywhere. Removing an import from one file can inadvertently break code in other files. To alleviate this problem, alternative imports in the form of lettable operators are available since RxJS 5.5.
JavaScript's Array prototype provides a comprehensive selection of methods which lend themselves nicely to functional programming approach, such as ma and reduce. Surprisingly, when doing code reviews I often see that developers are not aware of them or not used to using them. In this post, I'll do an overview of these functions with examples how they can simplify your code.
Ionic Native makes it very convenient to use Cordova plugins from Ionic applications. Although Ionic Native provides an impressive collection of wrappers for many Cordova plugins, there are still Cordova plugins out there without a corresponding plugin. In such cases you will need to either use them directly without a wrapper or write your own wrapper. The latter option is much simpler than you might think.
The biggest advantage of having a formal description for a RESTful API is the ability to programmatically generate client-side code for calling the service. Unfortunately, it turned out that Swagger tooling still leaves much to be desired, at least for generating TypeScript Angular code.
I keep getting impressed by how feature-rich dependency injection in Angular is. This time I needed it to inject the appropriate implementation of a dependency based on runtime information. Of course, the scenario is well supported.
Angular has great support for validating data in forms, both template-driven and and reactive ones, built imperatively with FormGroup. It is also easy to create own custom validators. However, I did not find it obvious, how to use injected dependencies in non-directive validators for reactive forms.
Many Angular 2 and Ionic 2 APIs return RxJS observables. To unit test your code that's consuming them, you will need to create your own observable streams with test data. With this approach I wrote tests for code reacting to user's current geolocation.
Angular makes heavy use of ECMAScript 2015 modules. All components and other Angular objects are modules themselves, therefore the tutorials explain early on, how to import and use them. However, how does one import a third party library which still exports legacy CommonJS or AMD modules?
By default, Ionic 2 produces unminified development builds. To force an optimized production build, you need to add --prod switch to ionic build or ionic run command. Since development build doesn't include Angular AoT (Ahead of Time) compilation, your production build might turn out broken even if development build of the application worked just fine.
In version 2.1 that was released in December 2016, TypeScript finally added support for downlevel transpilation of async and await keywords for ES3 and ES5 targets. To give this new feature a try, I decided to convert the Angular Tour of Heroes tutorial to use async and await.
In my previous posts I've already addressed unit testing of client-side JavaScript and TypeScript code, however since browsers don't natively support the ECMAScript 6 module system, simply transpiling the code is not enough for the tests to run in the browser.
Having unit tests usually drastically reduces the need for interactive debugging. However, being able to debug unit tests can sometimes prove very useful. Nowadays, any browser includes a fully featured debugger as part of its developer tools, and Karma test runner has a dedicated feature for in-browser debugging. I wrote short instructions on how exactly to use this feature for a project I am working on.
Although, I have now configured my Cordova project to automatically copy distribution files from installed Bower packages and reference them from HTML pages, there's still one final part of Bower-related configuration left: unit tests also require Bower dependencies. I don't want to manually update the configuration of my test runner every time I install an additional Bower package.
Visual Studio Tools for Apache Cordova is a Visual Studio extension for developing Cordova apps inside Visual Studio. Although it comes with a TypeScript based project template, it is not fully preconfigured for package managers that can simplify the use of JavaScript libraries and TypeScript definitions. This post describes how I configured a project I recently started working on.
I first stumbled across wallaby.js while working on my previous articles about continuous testing in the JavaScript ecosystem using Karma. After reading more about it in Scott Hanselman's blog post, I decided to try it out myself.
After taking a closer look at continuous testing of JavaScript code, I'm moving on to other languages that transpile to JavaScript. I'll mostly be focusing on TypeScript, but there aren't many differences with other languages. I'll mention some of them at the end of this post.
I have no reservations about recommending the book to any existing or future TypeScript developer. It can serve as the first book to start learning the language, but can teach you a lot even if you have already been programming in it for a while.