-
Book Overview & Buying
-
Table Of Contents
-
Feedback & Rating

The TypeScript Workshop
By :

Depending on the types of applications that you build, you may never need to build your own declaration files. However, if you're using TypeScript and working with third-party modules, you will need to understand how declaration files work because you will then be able to work seamlessly with external libraries.
Let's jump back in time for a moment. When TypeScript was originally developed, there was quite a bit of excitement around the idea of integrating types into JavaScript applications. However, developers began to get frustrated, because even though they were building their programs with types, every time that they imported an external library, such as lodash, they were forced to write code with no type signatures and little to no IDE guidance.
Essentially, this meant that each time we were to call a function from an external library, we didn't have a high level of assurance that we were working with it properly.
Thankfully, the open source community had the answer, and the DefinitelyTyped library was created. DefinitelyTyped is a very large repository that contains literally thousands of declaration files for JavaScript code libraries. This means that libraries such as react
, lodash
, and pretty much every other popular library has a full set of declaration files that we can use in our TypeScript programs.
Note
For more information on DefinitelyTyped, visit https://definitelytyped.org.
Before we learn how to import and use types with external libraries, let's peek into what they look like:
Figure 2.10: Example of how DefinitelyTyped uses declaration files
In the preceding screenshot, if you look at the lodash
declaration file for the array data structure, you'll see that a single declaration file is over 2,000 lines long. That can be a little intimidating to look at, so let's try to simplify it.
Note
lodash
is a utility library that provides functionality for working with objects, strings, arrays, and suchlike. The lodash
library's declaration file for the array data structure, as shown in the preceding screenshot, can be found here: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/lodash/common/array.d.ts.
You'll be pleased to know that the elements in the preceding declaration file are exactly what we built out in Exercise 1.01: Creating a Declaration File from Scratch. It starts by declaring a module
instance, and from that point, it lists out interfaces for each of the elements that utilize the array data structure. In fact, if you dissect the code, you'll see that lodash
provides three interfaces for each of the functions in the library. You don't have to know what these do; however, it is helpful to realize that you can provide as many interfaces as needed when you're building your own code libraries.
Let's now look at the interface for the last
function:
Figure 2.11: How lodash implements interfaces
This is a good function to look at, because we'll use it when we get to the example for this section. You can see that the majority of the interface is actually a comment. If you've never seen this syntax before, it is using JSDoc syntax. This is very helpful, because IDEs such as Visual Studio Code will pull the comment, parameters, and return type directly into the IntelliSense interface. This means that when we start typing the last
function when working with lodash
, the IDE will automatically pull in the comment data so we can easily read how to use the function.
After that, the declaration is pretty basic. It simply describes the shape of the last function, specifically, that it takes a list of values as the argument and then returns either T
or undefined
. Don't worry about all the references to T
; you'll learn about what this represents in Chapter 8, Generics. For now, just know that it means that it is returning a value.
Following the same pattern from when we created the declaration file from scratch, in the next section, let's create a new TypeScript project and walk through a practical example of why types are needed.
In this exercise, we'll install types and integrate our types with external libraries. We will also be exploring a scenario wherein we'll check how the function behaves when the wrong type of parameter is passed to it. You'll need to start with an empty directory for this exercise.
Note
The code files for this exercise can be found here: https://packt.link/k7Wbt.
Perform the following steps to implement this exercise:
npm init -y
The preceding code will generate a package.json
file.
npm i lodash
The preceding command installs the Lodash library. The package.json
file should now look something like this, with lodash
installed in the dependencies list:
Figure 2.12: The generated package.json file
lodash_examples.ts
, start the TypeScript compiler, and have it watch for changes. Inside of the new .ts
file, add the following code:import _ = require("lodash"); const nums = [1, 2, 3]; console.log(_.last(nums));
tsc lodash_examples.ts node lodash_examples.js
The console generates an output of 3
, as you can see in the following screenshot:
Figure 2.13: Running the generated lodash_example.js program
number
and assign it the value 10
. We'll then pass this number as an argument to the Lodash library's _.last()
function. Write the following code to do this:import _ = require("lodash"); //const nums = [1, 2, 3]; //console.log(_.last(nums)); const number = 10; console.log(_.last(number));
Since we've looked at the declaration file, we know that the last function expects an array or some type of list. However, for now, let's pretend that we don't have that information, and this is the first time that we're working with the Lodash library.
Note
The Lodash library's last
function also works with strings because it views the string of characters like a collection of characters. For example, _.last("hey")
will return "y"
since it's the last character in the string.
tsc lodash_examples.ts node lodash_examples.js
The following output is generated when the preceding commands are executed:
Figure 2.14: What happens when the wrong argument is passed to the last function
In such a small program, this may seem like a trivial issue. However, in a large system, getting an undefined value while expecting an actual value can be time-consuming, as we have to spend more time on debugging.
In order to fix this issue, let's leverage the DefinitelyTyped repository and bring in the lodash
types. If you hover over the import
statement at the top of the file, you'll even see the following warning and recommendation, as shown in the following screenshot:
Figure 2.15: TypeScript recommending to install Lodash types from DefinitelyTyped
That's quite helpful. The warning itself is showing us how we can install the types for the library.
lodash
types:npm install @types/lodash
Note
Any time that you see an install
command that starts with @types/
, that means that NPM is going to pull from the DefinitelyTyped repository.
If you run that command, the warning in the import
statement should go away automatically. But even more importantly, you should now see that the IDE is now complaining about the line of code where we're trying to pass a number to the last
function. If you hover over the word number
, you should see the error shown in the following screenshot:
Figure 2.16: IntelliSense revealing the correct type to use with the last function
From the preceding screenshot, it is clear that the last
function won't take any argument of the number
type. It accepts either an array or a list as an argument. So, let's imagine that we're building a real-world application, and we try to use the last
function. If we were using vanilla JavaScript, we wouldn't realize our error until we, or even a user, encountered the error while running the program. However, by leveraging TypeScript and DefinitelyTyped, the program won't even compile if we attempt to use a function in the incorrect manner.
Now that you've seen how to install and work with types, we will walk through a full development workflow so that you can observe the benefits of working with types. Without the integration of types into external libraries, we are forced to either have prior knowledge of the library or dig through the documentation to discover the proper usage.
However, with types, we're going to see how much more streamlined the process is when it comes to working with libraries such as lodash
. Let's solve an exercise in the next section to get a proper understanding of this.
In this exercise, we'll create a baseball lineup application, wherein we have an array of player names that we'll be retrieving from an API, and then we have a constant variable in the application called lineupOrder
. Our lineup card application needs to pair the names from the API with lineupOrder
:
Note
The code files for this exercise can be found here: https://packt.link/01spI.
lodash_newexamples.ts
and add the following code, wherein we have an array variable, playerNames
, and a list, lineupOrder
:import _ = require("lodash"); const playerNames = [ "Springer", "Bregman", "Altuve", "Correa", "Brantley", "White", "Gonzalez", "Kemp", "Reddick" ]; const lineupOrder = [1, 2, 3, 4, 5, 6, 7, 8, 9];
This is a perfect situation for using the zip
function from the Lodash library. Let's imagine that we've heard about the zip
function, but aren't quite aware of how to use it yet. Start by writing the following code in the same file:
_.zip()
Figure 2.17: IntelliSense guidance on how to use the zip function in lodash
Note
From the preceding screenshot, we can see that the zip
function takes two arguments. Both arguments need to be ArrayLike
, which means they need to function as a type of collection. Also, the function groups the elements together and returns the grouped collection. Thus, without having to dig through the lodash
documentation, we were able to leverage the type definition as we were building the program. It gives us the guidance we need while working with the function.
Let's now test it out. We know that the zip
function takes in two arrays. So, let's provide it with the playerNames
and lineupOrder
arrays.
zip
function with two arrays, playerNames
and lineupOrder
:console.log(_.zip(lineupOrder, playerNames));
If you run the preceding code, you'll see that the zip
function does exactly what it said it would do. It groups the elements and returns the exact data structure that we needed. The rendered lineup card would look something like that shown in the following screenshot:
Figure 2.18: Running the zip function properly from lodash
In completing this process, you can see how DefinitelyTyped allows you to extend types directly into third-party libraries so that you can get type guidance in your programs.
In this activity, you will build a TypeScript application named heat map log system
for tracking baseball pitch data and ensuring data integrity. You will utilize a TypeScript declaration file to build the type system for the program. From that point, you will import the Lodash library and will add type checking to the program by implementing type definitions from DefinitelyTyped.
The steps are as follows:
heat_map_data.ts
.HeatMapTypes
and export the interface named Pitcher
.Pitcher
module: batterHotZones
, pitcherHotZones
, and coordinateMap
.Array<Array<number>>
, but coordinateMap
should be optional.heat_map_data.ts
file. Then, create and export a let
variable called data
and assign it to the Pitcher
type.batterHotZones
and pitcherHotZones
attributes.findMatch
that takes in both the batterHotZones
and pitcherHotZones
arrays and utilize the lodash
function, intersectionWith
, to return the identical nested array. You will need to import the Lodash library, which was installed when you initially ran npm install
. Finally, store the value of findMatch
in the coordinateMap
attribute that was defined in the declaration file.The expected output of this activity will be a nested array that looks similar to this:
[[10.2, -5], [3, 2]]
Note
The solution to this activity can be found via this link.
Change the font size
Change margin width
Change background colour