Files
2026-09-21 20:34:38 +01:00

328 lines
7.5 KiB
TypeScript

//1. implicit type inference ///
let language = "Jeannette"; // inferred as string
let year = 2026; //inferred as number
//console.log(language)
//1.1. explicit Type annotations - slide 10 ///
let age: number = 100;
let isPresenter: boolean = true;
let emptyValue: null = null;
let notAssigned: undefined = undefined;
//1.2. type any ///
let value: any;
value = 123; // ok
value = "123"; // ok
value = true; // ok
//1.3. type union - allows a value to be one of several types, defined using the pipe (|) symbol. ///
type IDD = string | number;
function printId(id: IDD) {
// Type narrowing with typeof
if (typeof id === "string") {
console.log(`ID string in uppercase: ${id.toUpperCase()}`);
} else {
console.log(`Numeric ID multiplied: ${id * 10}`);
}
}
//printId(101); // Valid
//printId("task_abc"); // Valid
// printId(true); // Error: Argument of type 'boolean' is not assignable to parameter of type 'string | number'.
//2. Array - slide 11///
let techStack: string[] = ["TS", "JS", "Node", "Next.js"];
let scores: Array<number> = [1, 2, 3, 4, 5, 500];
let fruits: Array<string> = ["orange", "apple", "berry"];
//console.log(techStack)
//console.log(fruits)
// what is the type of below array?
let array1 = ["CMP6057A", 6057, true];
//let array2: (string | number | boolean)[] = ["CMP6057A", 6057, true]
//2.1. tuples - fixed-length arrays where each index has a specific type
let httpStatus: [number, string] = [200, "OK"];
//console.log(httpStatus[1])
//2.2. objects //
let object: object; //ok
object = {}; // ok
object = []; // ok but why?
let user: { id: number; name: string; isAdmin?: boolean } = {
id: 1,
name: "JC",
};
//console.log(user)
//2.3. Enums : name constants ///
enum Role {
Admin = "Admin",
User = "User",
Guest = "Guest",
}
let currentRole = Role.Admin;
//console.log(currentRole)
//3. Type alias - slide 13 & 14 //
type ID = string | number;
type OrderStatus =
| "pending"
| "processing"
| "shipped"
| "delivered"
| "cancelled";
type Order = {
id: ID;
status: OrderStatus;
totalAmount: number;
};
function updateOrderStatus(orderID: ID, newStatus: OrderStatus): void {
console.log(`order ${orderID} moved to status ${newStatus}`);
}
//updateOrderStatus("order 12344", "shipped");
//updateOrderStatus("order 9999", "refunded");
/// slides for complex examples slide 15 - 17 //
///3.1. interface - slide 18 ///
interface Vehicle {
make: string;
model: string;
}
interface Car extends Vehicle {
isElectric: boolean;
}
const tesla: Car = {
make: "Tesla",
model: "Model 3",
isElectric: true,
};
//console.log(tesla);
//3.2. index signature - slide 19 //
interface OrderObj {
Banana: number;
Sugar: number;
Potato: number;
Egg: number;
Milk: number;
}
const myOrders: OrderObj = {
Banana: 3,
Sugar: 1,
Potato: 2,
Egg: 6,
Milk: 1,
};
//console.log(myOrders.Egg); //6
// const totalOrder = (orders:OrderObj):number => {
// let total = 0;
// for (const order in orders) {
// total += orders[order]
// }
// return total
// }
// console.log(totalOrder(myOrders))
///12. rest parameters - allows a function to accept any number of arguments as an array , TS ensures every passed argument matches the declared array element type - slide 20 ///
function multiply(factor: number, ...numbers: Array<number>): Array<number> {
return numbers.map((n) => n * factor);
}
//console.log(multiply(2, 1,3,5,7)) // 2,6,10,14
/// more examples //
type UserLoginArgs = [userID: number, timestamp: Date];
type SystemErrorArgs = [errorCode: number, message: string, isFatal: boolean];
function logUserLogin(...args: UserLoginArgs): void {
const [userID, timestamp] = args;
console.log(`User ${userID} logged in at ${timestamp.toISOString()}`);
}
//logUserLogin(1234, new Date())
function logSystemError(...args: SystemErrorArgs): void {
const [code, message, fatal] = args;
console.log(`Error ${code}, ${message} | Fatal: ${fatal}`);
}
//logSystemError(500, "DB Error", true);
///13. Type Never : A function has the return type never if it either always throws an error or never terminates. slide 22 & 23 ///
// Always throws an exception
function fail(message: string): never {
throw new Error(message);
}
// Runs an infinite loop
function runForever(): never {
while (true) {
// Background polling, daemon loop, etc.
}
}
///Exhaustive Type Checking (default Cases)
// The most common real-world use of never is ensuring that all members of a union are handled at compile time.
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function getArea(shape: Shape): number {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.side * shape.side;
default: {
// If all cases are handled, `shape` is narrowed down to `never`.
const _exhaustiveCheck: never = shape;
throw new Error(`Unhandled shape: ${_exhaustiveCheck}`);
}
}
}
//If you later add { kind: "triangle" } to Shape without updating the switch statement, TypeScript will flag a compile-time error: Type 'Triangle' is not assignable to type 'never'. //
///14. Assertion "as" slide 24 //
// Example with unknown (e.g., from an external API or JSON.parse)
const rawData: unknown = "advanced WebDev 001 assessment";
// Without assertion, rawData.length throws an error: Object is of type 'unknown'
const titleLength = (rawData as string).length;
//console.log(titleLength); // 30
// document.getElementById returns HTMLElement | null
// HTMLInputElement gives access to .value, .checked, etc.
const inputElement = document.getElementById(
"username-input",
) as HTMLInputElement;
//console.log(inputElement.value); // Valid: value exists on HTMLInputElement
///15. Generics <T> slide 25 & 26 ///
function wrapInArray<T>(item: T): T[] {
return [item];
}
const numberArray = wrapInArray(1234);
const stringArray = wrapInArray("WebDev");
//console.log(numberArray)
//console.log(stringArray)
interface ApiResponse<Data> {
status: number;
success: boolean;
payload: Data;
}
interface UserPayload {
username: string;
}
const response: ApiResponse<UserPayload> = {
status: 200,
success: true,
payload: { username: "JC" },
};
//console.log(response.payload);
///16. utility slide26//
interface Task {
id: number;
title: string;
description: string;
completed: boolean;
}
//16.1 Partial<T> makes all properties in T optional //
function updateTask(task: Task, fieldsToUpdate: Partial<Task>): Task {
return { ...task, ...fieldsToUpdate };
}
const myTask = {
id: 123,
title: "001 assignment",
description: "advanced WebDev 001 assessment",
completed: false,
};
//updateTask(myTask, {completed:true})
//console.log(myTask) // complete = false , why?
//16.2 Required <T> //
type CompleteTask = Required<Task>;
//16.3 Readonly<T> //
type ImmutableTask = Readonly<Task>;
//16.4 Pick<T, K> selects a set of properties K from T
type TaskPreview = Pick<Task, "id" | "title">;
//Omit<T, K> removes properties K from T
type TaskForm = Omit<Task, "id">;
const preview: TaskPreview = { id: 100, title: "Review Assignment" };
const formInput: TaskForm = {
title: "Release 001",
description: "release 001 assignment",
completed: false,
};
//16.5 Record<K, T> construct an object map from keys K to values T //
type UserRole = "admin" | "editor" | "viewer";
const permission: Record<UserRole, string[]> = {
admin: ["read", "write", "delete"],
editor: ["read", "write"],
viewer: ["read"],
};
// console.log(permission.editor)