# TypeScript
# Setup
$ npm install -g typescript Install typescript.
# Compiling TypeScript
$ tsc fileName.ts fileName.js Compile typescript file to javascript file.
$ tsc fileName.ts -w Watch fileName.ts and compile automatically on save to fileName.js.
# Type Basics
- Types can not be changed and are inferred once declared
# Boolean
let isDone: boolean = false;
# Number
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;
let big: bigint = 100n;
# String
let name: string = "bob";
name = 'sam';
// using template strings
let car: string = "Ford Ranger"
let year: number = 2020;
let statement: string = `This is a ${year} ${car}, last year's model ${year - 1};
# Array
let list: number[];
let list: Array<number> = [1, 2, 3];
// union types
let mixed: (string | number)[] = [];
mixed.push('hello');
mixed.push(10);
# Tuple
- Specify types and fixed position in an array
let tup: [string, boolean, number] = ['Ben', true, 120];
let values: [string, string, number];
values = [tofrom.value, details.value, amount.valueAsNumber];
if (type.value === 'invoice') {
doc = new Invoice(...values);
} else {
doc = new Payment(...values);
}
# Enum
- Storing a set of constant or keywords and associate with numeric value.
enum ResourceType {
BOOK,
FILM,
TV,
}
interface Resource<T> {
uid: number;
resourceType: ResourceType;
data: T;
}
const docOne: Resource<object> = {
uid: 1,
resourceType: ResourceType.BOOK,
data: { tile: 'The Awesome Book' },
};
console.log(docOne);
// Output: {uid: 1, resourceType: 0, data: {title: "The Awesome Book"}}
# Unknown
- Any (Dynamic type)
let uid: any = 25;
uid = 'xoci12';
# Void
# Null and Undefined
# Never
# Object
let itemOne = Object;
item = { name: 'Box', price: 21.0 };
let itemTwo: {
name: string,
price: number,
isActive: boolean,
};
# tsconfig
tsc --init create tsconfig.json
{
"compilerOptions": {
"target": "est5",
"module": "commonjs",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true,
"public": "./public",
"rootDir": "./src"
},
"include": ["src"],
"exclude": ["node_modules", "**/*.spec.ts"]
}
# Function
let greet: Function;
let hello = (msg): void => {
console.log('hello' + msg);
};
// returns Void when not returning anything
const add = (a: number, b: number = 10, c?: number | string) => {
a + b;
};
add(2, 5);
// b default value is 10, c is an optional argument with optional type number or string
# Type Aliases
- Type aliases are used to create a new name for an existing type.
// Union & Premitive type
type StrNum = string | number;
type ObjectWithName = { name: string; uid: strNum };
const log = (uid: strNum, item: string) => {
console.log(`${uid} has ${item}`);
};
const greet = (user: objWithName) => {
console.log('Hello' + user);
};
// Function type
type InputChange = (value: StrNum) => void;
# Interfaces
Use to enforce type.
interface Item {
name: string;
sku: number;
status(a: string): void;
totalVolume(quantity: number): number;
}
let tray: Item;
// Conditional types
# Type Aliases vs Interfaces
// Extending interfaces
interface Orders {
id: number;
status: string;
}
interface SalesOrders extends Orders {
customer: string;
}
// Extending type aliases
type Orders = {
id: number;
status: string;
};
type SalesOrders = Orders & {
customer: string;
};
// Adding properties to interfaces
interface Item {
name: string;
sku: number;
}
interface Item {
status: string;
}
// A type cannot be changed after it is declared
# Function Signatures
let calc: (a: number, b: number, c: string) => number;
calc = (numOne: number, numTwo: number, action: string) => {
if (action === 'add') {
return numOne + numTwo;
} else {
return numOne - numTwo;
}
};
// if not returning anything => void
let logDetails: (obj: { name: string; age: number }) => void;
logDetails = (user: { name: string; age: number }) => {
console.log(`${user.name} is ${user.age} years old`);
};
# The DOM & Type Casting
// ! Exclamation mark is the non-null assertion operation, assert this exist
let anchor = document.querySelector('a')!;
// Type casting to identify type
const form = document.querySelector('.net-item-form') as HTMLFormElement;
const type = document.querySelector('#type') as HTMLSelectElement;
const amount = document.querySelector('#amount') as HTMLInputElement;
# Classes
// classes
class Invoice {
client: string;
details: string;
amount: number;
constructor(c: string, d: string, a: number) {
this.client = c;
this.details = d;
this.amount = a;
}
format() {
return `${this.client} owes USD${this.amount} for ${this.details}`;
}
}
// only invoices in array
let invoices: Invoice[] = [];
const invOne = new Invoice('bob', 'website', 250);
# Interfaces with Classes
Use interface to enforce structure in classes
- interfaces/HasFormatter.ts
export interface HasFormatter {
format(): string;
}
- classes/Invoices.ts
import { HasFormatter } from ".../interfaces/HasFormatter.ts"
export class Invoice implements HasFormatter {
format() {
returns "hello"
}
}
# Public, Private, & Readonly
class Invoice {
constructor(
public client: string, // default, read and change value in and outside class
private details: string, // read and change only within class
readonly amount: number // only allow read in and out of class, cant change value
) {}
}
# Modules
- In tsconfig.json
{
"compilerOptions": {
"target": "es6",
"module": "es2015"
}
}
- index.html
<script type="module" src="app.js"></script>
- src/classes/invoice.ts
export class Invoice {}
- src/app.ts
import { Invoice } from './classes/Invoices.js';
# Rendering an HTML Template
# Generics
- Captures whatever types/properties that is passed into argument
const addUID = <T extends {name: string}>(obj: T) => {
let UID = Math.floor(Math.random() * 100);
return { ...obj, uid };
};
let docOne = addUID(name:"bob", age: 30)
// with interfaces
interface Resource<T> {
uid: number;
name: string;
data: T
}
const docThree: Resouce<object[]> = {
uid: 1,
name: "Bob",
data: [{age: 10}, {age: 12}]
}
# Type Guard
typeof: number, string, boolean, symbolinstanceof: other value created with constructor function