There are (at least) 3 bugs in this code. Can you spot them?
<input id="a" type="number" /> +
<input id="b" type="number" /> =
<span id="result "></span>
<script>
const aInput = document.getElementById("a");
const bInput = document.getElementById("b");
const resultSpan = document.getElementById("result");
const computeResult = () =>
(resultSpan.value = aInput.value + bInput.value);
aInput.addEventListener("input", computeResult);
bInput.addEventListener("input", computeResult);
computeResult();
</script>
A type system is a syntaxic method for automatically checking the absence of certain erroneous behaviors by classifying program phrases according to the kinds of values they compute.
— Benjamin C. Pierce, Types and Programming Languages
Typescript (example 2):
const foo: number = 42;
Python (example 3):
foo: int = 42
C:
int foo = 42;
const foo: number = 42;
const bar: string = "Hello world";
const baz: boolean = true;
const qux: undefined = undefined;
const quux: null = null;
const foo: number[] = [42, 451, 1984];
const bar: string[] = ["Hello Bradbery", "Hello Orwell"];
const baz: boolean[] = [false, false, true];
function greet(name: string) {
console.log("Hello " + name);
}
greet("Ada");
function greet(name: string): string {
return "Hello " + name;
}
console.log(greet("Ada"));
function add(a: number, b: number): number {
return a + b;
}
console.log(add(40, 2));
const center: { x: number; y: number } = { x: 0, y: 0 };
// The parameter's type annotation is an object type
function printCoord(point: { x: number; y: number }) {
console.log("The coordinate's x value is " + point.x);
console.log("The coordinate's y value is " + point.y);
}
printCoord(center);
const foo: number | string = 42;
const bar: number | string = "";
const baz: number | undefined = 42;
const qux: number | undefined = undefined;
type Human = { firstname: string; lastname: string };
type Robot = { serialNumber: number };
function printName(member: Human | Robot) {
// ...
}
interface Human {
firstname: string;
lastname: string;
}
interface Robot {
serialNumber: number;
}
interface Human {
firstname: string;
lastname: string;
}
interface Developer extends Human {
githubRepo: string;
}
To differentiate one value (like null or undefined) from other values, we can use an equality check.
function getLength(arg: string | undefined): number {
if (arg === undefined) {
return 0;
} else {
return arg.length;
}
}
typeof type guardsTo differentiate a primitive type from another, we can use the typeof keyword that returns the type of a variable as a string. This only works for primitive types (string, number, boolean, undefined or null).
function sinOrLength(arg: number | string): number {
if (typeof arg === "number") {
return Math.sin(arg);
} else {
return arg.length;
}
}
Used to differentiate between interface types.
interface Human {
type: "human";
firstname: string;
lastname: string;
}
interface Robot {
type: "robot";
serialNumber: number;
}
function printName(member: Human | Robot) {
if (member.type === "robot") {
console.log(member.serialNumber);
} else {
console.log(member.firstname + " " + member.lastname);
}
}
instanceof narrowingUsed to differentiate between class types.
class Human {
firstname: string;
lastname: string;
// constructor ...
}
class Robot {
serialNumber: number;
// constructor ...
}
function printName(member: Human | Robot) {
if (member instanceof Robot) {
console.log(member.serialNumber);
} else {
console.log(member.firstname + " " + member.lastname);
}
}
TypeScript files cannot be directly understood by a web browser. We need to compile them to JavaScript first.
In order to do so, we will use Node.js, NPM, Webpack and the TypeScript compiler.
Node.js allows to run JavaScript outside of the browser.
We will it use for two purpose:
The Node Package Manager (NPM) is used to manage the dependencies of a project.
Each NPM project contains a package.json file that declares the dependencies of the project and other metadata.
package.json file{
"name": "[your-exercise-name]",
"version": "1.0.0",
"author": "[your-name]",
"private": true,
"scripts": {
"build": "webpack",
"build:watch": "webpack --watch"
},
"devDependencies": {
"ts-loader": "^9.2.3",
"typescript": "^4.3.2",
"webpack": "^5.38.1",
"webpack-cli": "^4.7.0"
}
}
Webpack is the build tool we will use. It can convert files from one language to another and bundle them together. We will use it to convert all TypeScript files from the src directory to a single JavaScript file dist/bundle.js.
Webpack is configured by a webpack.config.js file.
webpack.config.js fileconst path = require("path");
module.exports = {
entry: "./src/main.ts",
mode: "development",
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/,
},
],
},
resolve: {
extensions: [".tsx", ".ts", ".js"],
},
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
},
};
The TypeScript compiler itself also can be configured, using a tsconfig.json file.
We will use the following:
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true
}
}
Reproduce the degrees converter from Google search:

The page should contain two <input>: one with the value in Celsius degrees and the second in Fahrenheit degrees.
Changing the value of one input should automatically update the value of the other.
Make sure that this also work if an input is empty.
Under each input, there should be a <select> element allowing to change the degrees unit (“Fahrenheit”, “Celsius” or “Kelvin”), as in the Google widget.
Use data as a single source of truth, and derive the view from it.
The view should never update itself directly.
02-typescript/examples/05-array-sum example, or from your first exercise, to a folder 02-typescript/02-to-do-list in your exercises repository (so that you have all the configuration files ready).npm install.src/main.ts file.npm run build (to compile once) or npm run build:watch (to automatically recompile on every change).State typeState type representing the state of your application. It should be an array of objects, each with an attribute done and an attribute title.state variable of type State.render functionWrite a render function that renders the state to the DOM.
Add a way to add a new item to the to-do list.
Display a checkbox for each item showing if the item is done or not. Clicking on the checkbox should change the value of the corresponding done attribute.
The to-do items should always be sorted alphabetically.
Each time the state changes, save it to local storage so that it can be restored on next page load.
Add a way to show only items that are done or not done.
Remember ES6 classes?
class Human {
constructor(firstname, lastname) {
this.firstname = firstname;
this.lastname = lastname;
}
}
With type annotations:
class Human {
firstname: string;
lastname: string;
constructor(firstname: string, lastname: string) {
this.firstname = firstname;
this.lastname = lastname;
}
}
Here, ada is a POJO (Plain Old JavaScript Object), created using the object literal notation ({ ... }):
interface Human {
firstname: string;
lastname: string;
}
const ada: Human = {
firstname: "Ada",
lastname: "Lovelace",
};
Here ada is an instance of the Human class, constructed with the new keyword:
class Human {
firstname: string;
lastname: string;
constructor(firstname: string, lastname: string) {
this.firstname = firstname;
this.lastname = lastname;
}
}
const ada: Human = new Human("Ada", "Lovelace");
The main added value of a class is the possibility to add methods:
class Human {
firstname: string;
lastname: string;
constructor(firstname: string, lastname: string) {
this.firstname = firstname;
this.lastname = lastname;
}
toString(): string {
return this.firstname + " " + this.lastname;
}
}
const ada: Human = new Human("Ada", "Lovelace");
ada.toString(); // "Ada Lovelace"
MyHTMLElement classclass MyHTMLElement {
tagName: string;
constructor(tagName: string) {
this.tagName = tagName;
}
appendChild(child: MyHTMLElement) {}
}
Copy this code in a file 02-typescript/01-my-html-element.ts in your repository.
children attributeAdd a children attribute to the MyHTMLElement class so that the following code type-checks (for now, this means that nothing should be underlined in red in VSCode):
const element: MyHTMLElement = new MyHTMLElement("div", []);
element.children[0].tagName;
Question: in the real HTMLElement type, is the children attribute an array?
insertBefore methodWrite an insertBefore method declaration (without implementation) so that the following code type-checks:
const child: MyHTMLElement = new MyHTMLElement("span", []);
const element: MyHTMLElement = new MyHTMLElement("div", []);
element.insertBefore(child, new MyHTMLElement("span", []));
querySelector methodWrite a querySelector method declaration that takes a string as an argument and returns either a MyHTMLElement or null. Use return null; as implementation for now.
classList attributeAdd a classList attribute so that the following code type-checks:
element.classList.add("a-class");
element.classList.has("a-class");
element.classList.remove("a-class");
Write the methods’ implementations.