[toc]
ℹ️ NOTE: If this works out, a TypeScript Guide may ensue.
The final chapters of the first unit cover a framework called Angular. Angular runs on TypeScript for a couple of reasons.
First, TypeScript is a superset of JavaScript. That means you can write JavaScript code and use it in TypeScript files.
Second, TypeScript is a statically typed language, that is a language where the type of a varaible is given at the time the program is compiled. This is often achieved by adding the type of the variable to the variable declaration. However, that is no what we have been doing so far. JavaScript is a dynamically typed language, a language where the type of the variable is determined at runtime and is based on the value inside the variable, not the variable declaration.
Statically typed languages are considered to be more stable and less prone to production errors, because the error will occur in development.
As we continue to shift away from online work in repl.it (which is a P.I.T.A. to use in the first place) to local development on your computer, you need to install some specific software.
- If you haven't done so already: Download and install Visual Studio Code on your computer.
- Install Node on your computer, which also installs the NPM CLI. We discussed this briefly bac in the Modules chapter.
REMINDER: If you are using Windows, Chocolatey is the easiest way to install these things. I should have instructions in these notes for doing all this anyway! ( 🎗️TODO: Insert the link to that page later. )
The NPM CLI tool provides you with an efficient and deliberate way to install other software and modules onto your computer. As you proceed through the next four chapters, you will use the NPM CLI in the terminal to perform these installations.
Since TypeScript is statically typed, the type of the value is added to the variabl declaration. However we will still use or let and const keywords where appropriate.
The general format of a variable declaration is:
let variableName : type = value;let variableName : number = 10;let variableName : string = "10";let variableName : boolean = true;In TypeScript we write:
let spaceShuttleName : string = "Determination";
let shuttleSpeed : number = 17500;
let distanceToMars : number = 225000000;
let distanceToMoon : number = 384400;
let milesPerKilometer : number = 0.621;which compiles into JavaScript as
let spaceShuttleName = "Determination";
let shuttleSpeed = 17500;
let distanceToMars = 225000000;
let distanceToMoon = 384400;
let milesPerKilometer = 0.621;Arrays in TypeScript must contain values of the same type. When declaring an array, the type needs to be declared.
let arrayName : number[] = [10,9,8];What if the array needs to hold values of different types?
Nowe we need a tuple. A tuple is a special structure in TypeScript that can hold as many values needed of different types.
let tupleName: [number, string, number];
tupleName = [10,"9",8];🎗️ TODO: Write this section later.
When creating functions in TypeScript, we have many of the same options as in JavaScript. We can make anonymous functions, giving them a different number of parameters, etc. However, when working with functions in TypeScript, we have to kee data type in mind.
Let's take a look at a TypeScript function delaration.
Example: We want to declare a function called
myFunctionwith one parameter, a number calledx.myFunctionreturns the value ofxmultipled by 2.With this is mind, the declaration in TypeScript would look like:
function myFunction(x : number) : number { return x * 2; }Here you can see that we provided the type of the paramter and the type of the value returned after the colons. If
xwere a string or boolean, then we would replacenumberwith the data type ofx.
What if the function doesn't return a value? In these cases, we use void as the return type.
Example: Let's change up
myFunctiona little bit.myFunctionstill has one parameter, our number calledx, however it doesn't return a specific value.let y : number = 0; function myFunction(x : number) : void { y = x * 2; }Instead of returning the value of
xmultiplied by 2,myFunctionnow assigns the value ofxmultipled by 2 to another variabley. We can now usevoidto specify that no value is returned.
For an anonymous function, you still need to privide types for the value returned and the parameters.
Example: Nowe we want to declare an anonymous function
myFunction, which has one parameter, a number calledxand returns the value ofxmultipled by 2.let myFunction = function(x : number) : number { return x * 2; };
Just as we did above with the named function, we need to make sure that we include the data type for the parameters and the return type of the function.
🎗️ TODO: What about arrow functions?
In JavaScrit, you can declare a function with 5 parameters and only give it 2 when it comes times to use it. In TypeScript, that is not the case. In TypeScript, when you declare a function with 5 parameters, you have to give the function 5 arguments when calling it, unless you make some of the parameters optional. This means that when you are calling the function, can leave off the optional parameter(s).
To denote a parameter as optional, you can use question mark (?) notation. Any parameters that are optional must follow the required parameters.
Example:
function myFunction(a: number, b?: number): number { return a+b+5; } console.log(myFunction(1,2)); // 8 console.log(myFunction(1)); // 6 console.log(myFunction(3,5)); // 13 console.log(myFunction(3)); // 8
In this example, the myFunction function has two parameters, a and b. a is required and b is optional. When only one argument is provided to the function, then the value of a+5 is returned. When both arguments are provided, then the sum of the 2 arguments and 4 is returned.
Another way to deal with a parameter you need to be optional is to give a default value.
Let's say that in the example above, we wanted to give b a default value of 5. That way, if no argument is supplied for b, then the value returned is that of a+10.
Example:
function myFunction(a: number, b = 5): number { return a+b+5; } console.log(myFunction(1,2)); // 8 console.log(myFunction(1)); // 11 console.log(myFunction(3,5)); // 14 console.log(myFunction(3)); // 13🎗️ TODO: Should
bhave a type before= 5?
Because b has a default value of 5, when the user does not pass a value to the second argument of myFunction, 5 is used as the value of b.
Classes in TypeScript look something like this:
class Astronaut {
name: string;
constructor(firstName: string, lastName: string) {
this.name = firstName + " " + lastName;
}
greet() {
return "Hello, " + this.name;
}
}
let Bob = new Astronaut("Bob","Smith");You may remember the this and new keywords from working with classes in JavaScript. Earlier in the chapter, we also noted that when declaring variables in TypeScript, we have to specify the type of value. The same applies to function parameters, as you can see in the constructor.
When using inheritance, classes in Typescript can also use the extends keyword to denote child and parent classes, as shown here:
class Panthera {
roar: string;
constructor(currentRoar: string) {
this.roar = currentRoar;
}
}
class Tiger extends Panthera {
stripes: boolean = true;
}
let tigger = new Tiger("loud");
console.log(tigger.roar);
console.log(tigger.stripes);Interfaces are not used in JavaScript but are important in TypeScript. Like classes, interfaces define properties and methods that a type will have. The difference is that interfaces do NOT include initialization of properties or implementations of methods.
NOTE: Though the use of interfaces in Angular is not within the scope of this book, interfaces are used rather frequently in Angular code and are important in object-oriented programming languages, such as Java.
We may create an interface for a data type that contains all of the information we need about an astronaut and then used that information in a function.
interface Astronaut {
name: string;
}
function astronautName (astronaut: Astronaut) {
name: string;
return astronaut.name;
}
let bob = {name: "Bob"};
console.log(astronautName(bob));Interfaces define the contract that other classes or objects must comply with if implementing that interface. Multiple classes can implement one face, and that flexibility allows different classes to share one type. This can be helpful when a function parameter needs to make use of certain behaviors.
interface interfaceName {
someProperty: number;
}
class className implements interfaceName {
constructor(x: number) {
this.someProperty = x;
}
}Example:
interface Panthera { roar: string; } class Tiger implements Panthera { roar: string; constructor() { this.roar = 'rooooaaaarrrr'; } } class Lion implements Panthera { roar: string; constructor() { this.roar = 'ROOOOAAAAARRRRRR'; } } function pantheraSounds(panthera: Panthera) { console.log(`Panthera says ${panthera.roar}`); } let tiger = new Tiger(); let lion = new Lion(); pantheraSounds(tiger); pantheraSounds(lion);In this example, the
Pantherainterface defines theroarproperty.TigerandLionimplement thePantherainterface, which meansTigerandLionmust have aroarproperty.The function
pantheraSoundshas one property of typePanthera. The variablestigerandlioncan be passed intopantheraSoundsbecause they are instance of classes that implement thePantherainterface.
null and undefined are primative data types in TypeScript, however, they are treated differently by TypeScript. If you are planning on using null to define a property of an interface that is not known yet, use the TypeScript optional parameter, ?.
Here's how it would look in TypeScript.
In JavaScript, we might have an object that looks like this:
let giraffeTwo = {
species: "Reticulated Giraffe",
name: "Alicia",
weight: null,
age: 10,
diet: "leaves"
};If we wanted to declare the same object as an interface in TypeScript, we would have to use the optional parameter for the weight property.
interface giraffeTwo = {
species: string;
name: string;
weight?: number;
age: number;
diet: string;
};In TypeScript, you can use the export keyword to make classes and interfaces available for import in other files. This will look familiar to you as you saw something similar with modules.
Here's how it is typically used
export class className {
// properties
// methods
}In TypeScript, you can use the import keyword to use classes and interfaces declared in other files available for use in the file you are working on. This is a similar idea to importing modules, however, the syntax is different in TypeScript.
import { className } from 'relativeFilePath';
let newClass = new className;To work with TypeScript in our Node environment, we'll need to install the TypeScript module. We talked about running JavaScript in Node. Unlike JavaScript, TypeScript can't be run directly in Node. TypeScript files must be compiled (translated) into JavaScript.
In this section, you will install the compiler and then practice compiling and running a small TypeScript program from the terminal.
==To install TypeScript, type==
$ npm install -g typescript🍎/ 🐧 Mac/Linux users: You may receive a permission error when running this install command, add
sudoto the beginning of the command.
Once you have TypeScript installed, you'll be able to run
$ tsc -vtsc is the TypeScript compiler. The -v flag will show us the version of TypeScript that we have installed.
In true tutorial fashion, let's write a quick Hello, World program so we can see the compiler in action.
In you code editor, create a new file called hello_world.ts. In it, initialize a variable called message with a string value Hello, World, then print the message.
NOTE: Since this is a short program, why not use a simple text edtor like
nanoorvim?
/* @file hello_world.ts */
let message : string = 'Hello, World';
console.log(message);In the terminal, navigate to the directory that your hello_world.ts file is in and compile the code.
$ ls
hello_world.ts
$ tsc hello_world.ts
$ ls
hello_world.js hello_world.ts
$ node hello_world.js
Hello, WorldIf your TypeScript file is free of syntax errors, you won't see a respnse from the terminal directly. However, you should see that you hve a newly generated file in you working directory called hello_world.js.
If it compiles correctly, you should be able to run the hello_world.js file in node and see the classic Hello, World string.
NOTE: If you update you TypeScript file, you must re-compile it so that the changes are applied to the corresponding JavaScript file.
You'll need these compiling and executing steps for the exercises in the following section, so refer back here as needed.
#LaunchCode