diff --git a/README.md b/README.md index 9ff74ae..9041230 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ Feel free to take a look. You might learn new things. They have been designed to #### Functional - [JavaScript](languages/javascript.js) +- [Typescript](languages/typescript.md) @@ -73,6 +74,7 @@ Feel free to take a look. You might learn new things. They have been designed to --- + ### 🌐 Frontend
@@ -81,6 +83,7 @@ Feel free to take a look. You might learn new things. They have been designed to #### Basics - [HTML5](frontend/html5.html) - [CSS3](frontend/css3.css) +- [Typescript](frontend/typescript.ts) #### Frameworks - [React.js](frontend/react.js) @@ -89,7 +92,6 @@ Feel free to take a look. You might learn new things. They have been designed to - [Ember.js](frontend/ember.js) - [Angular (2+)](frontend/angular.js) - [AngularJS](frontend/angularjs.js) -
--- diff --git a/frontend/tailwind.css b/frontend/tailwind.css index 5051bd5..a18e218 100644 --- a/frontend/tailwind.css +++ b/frontend/tailwind.css @@ -43,11 +43,14 @@ .hidden /* display: none; */ .block /* display: block; */ + .flow-root /* display: flow-root; */ .inline-block /* display: inline-block; */ .inline /* display: inline; */ .flex /* display: flex; */ .inline-flex /* display: inline-flex; */ .grid /* display: grid; */ + .inline-grid /* display: inline-grid; */ + .contents /* display: contents; */ .table /* display: table; */ .table-caption /* display: table-caption; */ .table-cell /* display: table-cell; */ @@ -68,7 +71,6 @@ .float-right /* float: right; */ .float-left /* float: left; */ .float-none /* float: none; */ - .clearfix /* &::after { content: ""; display: table; clear: both; } */ /* * Clear @@ -130,8 +132,6 @@ .overflow-y-visible /* overflow-y: visible; */ .overflow-x-scroll /* overflow-x: scroll; */ .overflow-y-scroll /* overflow-y: scroll; */ -.scrolling-touch /* -webkit-overflow-scrolling: touch; */ -.scrolling-auto /* -webkit-overflow-scrolling: auto; */ /* * Position @@ -219,7 +219,7 @@ * By default, only responsive variants are generated for flex-wrap utilities. */ -.flex-no-wrap /* flex-wrap: nowrap; */ +.flex-nowrap /* flex-wrap: nowrap; */ .flex-wrap /* flex-wrap: wrap; */ .flex-wrap-reverse /* flex-wrap: wrap-reverse; */ @@ -478,44 +478,44 @@ .gap-56 /* gap: 14rem; */ .gap-64 /* gap: 16rem; */ .gap-px /* gap: 1px; */ -.row-gap-0 /* row-gap: 0; */ -.row-gap-1 /* row-gap: 0.25rem; */ -.row-gap-2 /* row-gap: 0.5rem; */ -.row-gap-3 /* row-gap: 0.75rem; */ -.row-gap-4 /* row-gap: 1rem; */ -.row-gap-5 /* row-gap: 1.25rem; */ -.row-gap-6 /* row-gap: 1.5rem; */ -.row-gap-8 /* row-gap: 2rem; */ -.row-gap-10 /* row-gap: 2.5rem; */ -.row-gap-12 /* row-gap: 3rem; */ -.row-gap-16 /* row-gap: 4rem; */ -.row-gap-20 /* row-gap: 5rem; */ -.row-gap-24 /* row-gap: 6rem; */ -.row-gap-32 /* row-gap: 8rem; */ -.row-gap-40 /* row-gap: 10rem; */ -.row-gap-48 /* row-gap: 12rem; */ -.row-gap-56 /* row-gap: 14rem; */ -.row-gap-64 /* row-gap: 16rem; */ -.row-gap-px /* row-gap: 1px; */ -.col-gap-0 /* column-gap: 0; */ -.col-gap-1 /* column-gap: 0.25rem; */ -.col-gap-2 /* column-gap: 0.5rem; */ -.col-gap-3 /* column-gap: 0.75rem; */ -.col-gap-4 /* column-gap: 1rem; */ -.col-gap-5 /* column-gap: 1.25rem; */ -.col-gap-6 /* column-gap: 1.5rem; */ -.col-gap-8 /* column-gap: 2rem; */ -.col-gap-10 /* column-gap: 2.5rem; */ -.col-gap-12 /* column-gap: 3rem; */ -.col-gap-16 /* column-gap: 4rem; */ -.col-gap-20 /* column-gap: 5rem; */ -.col-gap-24 /* column-gap: 6rem; */ -.col-gap-32 /* column-gap: 8rem; */ -.col-gap-40 /* column-gap: 10rem; */ -.col-gap-48 /* column-gap: 12rem; */ -.col-gap-56 /* column-gap: 14rem; */ -.col-gap-64 /* column-gap: 16rem; */ -.col-gap-px /* column-gap: 1px; */ +.gap-y-0 /* row-gap: 0; */ +.gap-y-1 /* row-gap: 0.25rem; */ +.gap-y-2 /* row-gap: 0.5rem; */ +.gap-y-3 /* row-gap: 0.75rem; */ +.gap-y-4 /* row-gap: 1rem; */ +.gap-y-5 /* row-gap: 1.25rem; */ +.gap-y-6 /* row-gap: 1.5rem; */ +.gap-y-8 /* row-gap: 2rem; */ +.gap-y-10 /* row-gap: 2.5rem; */ +.gap-y-12 /* row-gap: 3rem; */ +.gap-y-16 /* row-gap: 4rem; */ +.gap-y-20 /* row-gap: 5rem; */ +.gap-y-24 /* row-gap: 6rem; */ +.gap-y-32 /* row-gap: 8rem; */ +.gap-y-40 /* row-gap: 10rem; */ +.gap-y-48 /* row-gap: 12rem; */ +.gap-y-56 /* row-gap: 14rem; */ +.gap-y-64 /* row-gap: 16rem; */ +.gap-y-px /* row-gap: 1px; */ +.gap-x-0 /* column-gap: 0; */ +.gap-x-1 /* column-gap: 0.25rem; */ +.gap-x-2 /* column-gap: 0.5rem; */ +.gap-x-3 /* column-gap: 0.75rem; */ +.gap-x-4 /* column-gap: 1rem; */ +.gap-x-5 /* column-gap: 1.25rem; */ +.gap-x-6 /* column-gap: 1.5rem; */ +.gap-x-8 /* column-gap: 2rem; */ +.gap-x-10 /* column-gap: 2.5rem; */ +.gap-x-12 /* column-gap: 3rem; */ +.gap-x-16 /* column-gap: 4rem; */ +.gap-x-20 /* column-gap: 5rem; */ +.gap-x-24 /* column-gap: 6rem; */ +.gap-x-32 /* column-gap: 8rem; */ +.gap-x-40 /* column-gap: 10rem; */ +.gap-x-48 /* column-gap: 12rem; */ +.gap-x-56 /* column-gap: 14rem; */ +.gap-x-64 /* column-gap: 16rem; */ +.gap-x-px /* column-gap: 1px; */ /* * Grid Auto Flow @@ -1153,8 +1153,8 @@ * By default, only responsive, hover and focus variants are generated for font weight utilities. */ -.font-hairline /* font-weight: 100; */ -.font-thin /* font-weight: 200; */ +.font-thin /* font-weight: 100; */ +.font-extralight /* font-weight: 200; */ .font-light /* font-weight: 300; */ .font-normal /* font-weight: 400; */ .font-medium /* font-weight: 500; */ @@ -1479,7 +1479,7 @@ */ .whitespace-normal /* white-space: normal; */ -.whitespace-no-wrap /* white-space: nowrap; */ +.whitespace-nowrap /* white-space: nowrap; */ .whitespace-pre /* white-space: pre; */ .whitespace-pre-line /* white-space: pre-line; */ .whitespace-pre-wrap /* white-space: pre-wrap; */ @@ -1902,7 +1902,6 @@ * By default, only responsive, hover and focus variants are generated for box shadow utilities. */ -.shadow-xs /* box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.05); */ .shadow-sm /* box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); */ .shadow /* box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); */ .shadow-md /* box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); */ @@ -1910,9 +1909,34 @@ .shadow-xl /* box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); */ .shadow-2xl /* box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); */ .shadow-inner /* box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.06); */ -.shadow-outline /* box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.5); */ .shadow-none /* box-shadow: none; */ +/* + * RING + * -------------------- + * Utilities for creating outline rings with box-shadows. + * Replaced the old .shadow-outline utility. + */ + +.ring-0 /* box-shadow: 0 0 0 0px; */ +.ring-1 /* box-shadow: 0 0 0 1px; */ +.ring-2 /* box-shadow: 0 0 0 2px; */ +.ring-4 /* box-shadow: 0 0 0 4px; */ +.ring-8 /* box-shadow: 0 0 0 8px; */ +.ring /* box-shadow: 0 0 0 3px; */ +.ring-inset /* --ring-inset: inset; */ + +.ring-transparent /* --ring-color: transparent; */ +.ring-black /* --ring-color: #000; */ +.ring-white /* --ring-color: #fff; */ +.ring-current /* --ring-color: currentColor; */ + +.ring-offset-0 /* --ring-offset-width: 0px; */ +.ring-offset-1 /* --ring-offset-width: 1px; */ +.ring-offset-2 /* --ring-offset-width: 2px; */ +.ring-offset-4 /* --ring-offset-width: 4px; */ +.ring-offset-8 /* --ring-offset-width: 8px; */ + /* * OPACITY * -------------------- diff --git a/frontend/typescript.ts b/frontend/typescript.ts new file mode 100644 index 0000000..4647444 --- /dev/null +++ b/frontend/typescript.ts @@ -0,0 +1,670 @@ +/**************************** + * TYPESCRIPT CHEATSHEET - Quick Reference + * Learn more: https://www.typescriptlang.org/docs/ + * Playground: https://www.typescriptlang.org/play + * Handbook: https://www.typescriptlang.org/handbook/ + * + * Table of contents + * ------------------- + * 01 | Basic Types + * 02 | Variables & Arrays + * 03 | Functions + * 04 | Objects & Interfaces + * 05 | Classes + * 06 | Generics + * 07 | Union & Literal Types + * 08 | Type Guards & Assertions + * 09 | Utility Types + * 10 | Enums + * 11 | Modules + * 12 | Advanced Types + * 13 | Decorators + * 14 | Configuration + * 15 | Common Patterns + *****************************/ + +/*************************** +------------ 01: Basic Types ----------- +*******************************/ + +// Primitive Types +let str: string = "hello"; +let num: number = 42; +let bool: boolean = true; +let undef: undefined = undefined; +let nul: null = null; + +// Special Types +let anything: any = "can be anything"; +let unknown: unknown = "type-safe any"; +let nothing: void = undefined; +let never: never = (() => { throw new Error() })(); + +// Type Inference +let auto = "TypeScript infers string"; +let nums = [1, 2, 3]; // number[] + +/*************************** +------------ 02: Variables & Arrays ----------- +*******************************/ + +// Arrays +let numbers: number[] = [1, 2, 3]; +let strings: Array = ["a", "b"]; +let mixed: (string | number)[] = [1, "two"]; + +// Tuples +let tuple: [string, number] = ["hello", 42]; +let namedTuple: [name: string, age: number] = ["John", 30]; + +// Destructuring +let [first, second] = tuple; +let [x, y, ...rest] = [1, 2, 3, 4, 5]; + +// Object Destructuring +let {name, age} = {name: "John", age: 30}; +let {a: newName, b = 10} = {a: "value"}; // rename & default + +/*************************** +------------ 03: Functions ----------- +*******************************/ + +// Function Declaration +function add(x: number, y: number): number { + return x + y; +} + +// Arrow Functions +const multiply = (x: number, y: number): number => x * y; +const greet = (name: string): void => console.log(`Hello ${name}`); + +// Optional & Default Parameters +function build(first: string, last?: string, age = 25): string { + return `${first} ${last || ""} (${age})`; +} + +// Rest Parameters +function sum(...nums: number[]): number { + return nums.reduce((a, b) => a + b, 0); +} + +// Function Overloads +function format(x: string): string; +function format(x: number): string; +function format(x: string | number): string { + return x.toString(); +} + +// Function Types +type MathOp = (x: number, y: number) => number; +const divide: MathOp = (x, y) => x / y; + +/*************************** +------------ 04: Objects & Interfaces ----------- +*******************************/ + +// Object Types +let person: {name: string, age: number} = {name: "John", age: 30}; + +// Interface +interface User { + readonly id: number; + name: string; + email?: string; // optional + [key: string]: any; // index signature +} + +// Extending Interfaces +interface Admin extends User { + permissions: string[]; +} + +// Multiple Inheritance +interface Timestamped { + createdAt: Date; +} +interface AdminUser extends User, Timestamped { + role: "admin"; +} + +// Function in Interface +interface Calculator { + add(x: number, y: number): number; + subtract: (x: number, y: number) => number; +} + +/*************************** +------------ 05: Classes ----------- +*******************************/ + +// Basic Class +class Animal { + public name: string; + private age: number; + protected species: string; + readonly id: number; + + constructor(name: string, age: number) { + this.name = name; + this.age = age; + this.species = "unknown"; + this.id = Math.random(); + } + + speak(): void { + console.log(`${this.name} makes a sound`); + } +} + +// Inheritance +class Dog extends Animal { + breed: string; + + constructor(name: string, age: number, breed: string) { + super(name, age); + this.breed = breed; + } + + speak(): void { + console.log(`${this.name} barks`); + } +} + +// Abstract Class +abstract class Shape { + abstract area(): number; + + display(): void { + console.log(`Area: ${this.area()}`); + } +} + +// Static Members +class MathUtils { + static PI = 3.14159; + static circle(radius: number): number { + return 2 * MathUtils.PI * radius; + } +} + +// Getters/Setters +class Person { + private _age: number = 0; + + get age(): number { + return this._age; + } + + set age(value: number) { + if (value >= 0) this._age = value; + } +} + +/*************************** +------------ 06: Generics ----------- +*******************************/ + +// Generic Functions +function identity(arg: T): T { return arg; } +const result = identity("hello"); +const inferred = identity(42); // T inferred as number + +// Multiple Type Parameters +function pair(first: T, second: U): [T, U] { + return [first, second]; +} + +// Generic Interface +interface Container { + value: T; + getValue(): T; +} + +// Generic Class +class Box { + contents: T; + constructor(value: T) { + this.contents = value; + } +} + +// Constraints +interface HasLength { + length: number; +} + +function logLength(arg: T): void { + console.log(arg.length); +} + +// Keyof Constraint +function getProperty(obj: T, key: K): T[K] { + return obj[key]; +} + +/*************************** +------------ 07: Union & Literal Types ----------- +*******************************/ + +// Union Types +type StringOrNumber = string | number; +type Status = "loading" | "success" | "error"; + +function process(id: string | number): void { + if (typeof id === "string") { + console.log(id.toUpperCase()); + } else { + console.log(id.toFixed(2)); + } +} + +// Intersection Types +type Person = {name: string}; +type Employee = {company: string}; +type Staff = Person & Employee; // has both properties + +// Literal Types +type Theme = "light" | "dark"; +type Port = 3000 | 8080 | 9000; +type Success = true; + +// Discriminated Unions +interface Circle { + kind: "circle"; + radius: number; +} +interface Square { + kind: "square"; + sideLength: number; +} +type Shape = Circle | Square; + +function area(shape: Shape): number { + switch (shape.kind) { + case "circle": + return Math.PI * shape.radius ** 2; + case "square": + return shape.sideLength ** 2; + } +} + +/*************************** +------------ 08: Type Guards & Assertions ----------- +*******************************/ + +// Type Guards +function isString(value: any): value is string { + return typeof value === "string"; +} + +function isNumber(value: any): value is number { + return typeof value === "number"; +} + +// Using Type Guards +function process(value: string | number) { + if (isString(value)) { + console.log(value.toUpperCase()); // TypeScript knows it's string + } else { + console.log(value.toFixed(2)); // TypeScript knows it's number + } +} + +// in operator +type Fish = { swim: () => void }; +type Bird = { fly: () => void }; + +function move(animal: Fish | Bird) { + if ("swim" in animal) { + animal.swim(); // Fish + } else { + animal.fly(); // Bird + } +} + +// instanceof +function handleError(error: Error | string) { + if (error instanceof Error) { + console.log(error.message); + } else { + console.log(error); + } +} + +// Type Assertions +let someValue: any = "hello world"; +let strLength = (someValue as string).length; +// or: let strLength = (someValue).length; + +// Non-null Assertion +let name: string | null = getName(); +let nameLength = name!.length; // Assert name is not null + +/*************************** +------------ 09: Utility Types ----------- +*******************************/ + +interface Todo { + title: string; + description: string; + completed: boolean; +} + +// Partial - All properties optional +type PartialTodo = Partial; +// {title?: string, description?: string, completed?: boolean} + +// Required - All properties required +type RequiredTodo = Required; + +// Readonly - All properties readonly +type ReadonlyTodo = Readonly; + +// Pick - Select specific properties +type TodoPreview = Pick; + +// Omit - Exclude specific properties +type TodoInfo = Omit; + +// Record - Create object type +type TodoStatus = Record<"pending" | "completed", Todo[]>; + +// Exclude - Remove types from union +type NonString = Exclude; +// number | boolean + +// Extract - Extract types from union +type StringOnly = Extract; +// string + +// NonNullable - Remove null/undefined +type NonNullString = NonNullable; +// string + +// ReturnType - Get function return type +function getName(): string { return "John"; } +type NameType = ReturnType; // string + +// Parameters - Get function parameters as tuple +type GetNameParams = Parameters; // [] + +/*************************** +------------ 10: Enums ----------- +*******************************/ + +// Numeric Enum +enum Direction { + Up, // 0 + Down, // 1 + Left, // 2 + Right // 3 +} + +// String Enum +enum Color { + Red = "red", + Green = "green", + Blue = "blue" +} + +// Mixed Enum +enum Mixed { + No = 0, + Yes = "yes" +} + +// Const Enum (inlined at compile time) +const enum StatusCode { + OK = 200, + NotFound = 404, + Error = 500 +} + +// Usage +let currentDirection = Direction.Up; +let favoriteColor = Color.Blue; +let status = StatusCode.OK; + +/*************************** +------------ 11: Modules ----------- +*******************************/ + +// Named Exports +export const PI = 3.14159; +export function calculate(r: number): number { + return PI * r * r; +} +export class Calculator { + add(x: number, y: number): number { return x + y; } +} + +// Default Export +export default class Logger { + log(message: string): void { + console.log(message); + } +} + +// Re-exports +export { Calculator as Calc } from "./calculator"; +export * from "./utilities"; + +// Import +import Logger from "./logger"; // default import +import { PI, calculate } from "./math"; // named imports +import * as MathUtils from "./math"; // namespace import +import { Calculator as Calc } from "./calculator"; // alias + +// Dynamic Imports +const module = await import("./dynamic-module"); + +/*************************** +------------ 12: Advanced Types ----------- +*******************************/ + +// Mapped Types +type Nullable = { + [P in keyof T]: T[P] | null; +}; + +type OptionalId = { + [P in keyof T]: P extends "id" ? T[P] | undefined : T[P]; +}; + +// Conditional Types +type IsString = T extends string ? true : false; +type StringCheck = IsString<"hello">; // true + +// Template Literal Types +type EventName = `on${Capitalize}`; +type ClickEvent = EventName<"click">; // "onClick" + +// Indexed Access Types +type Person = { name: string; age: number; location: string }; +type PersonName = Person["name"]; // string +type PersonKeys = keyof Person; // "name" | "age" | "location" + +// Recursive Types +type Json = string | number | boolean | null | Json[] | {[key: string]: Json}; + +/*************************** +------------ 13: Decorators ----------- +*******************************/ + +// Class Decorator +function Component(name: string) { + return function(constructor: T) { + return class extends constructor { + componentName = name; + }; + }; +} + +@Component("MyComponent") +class MyClass {} + +// Method Decorator +function Log(target: any, propertyName: string, descriptor: PropertyDescriptor) { + const method = descriptor.value; + descriptor.value = function(...args: any[]) { + console.log(`Calling ${propertyName} with`, args); + return method.apply(this, args); + }; +} + +class Service { + @Log + getData(): string { + return "data"; + } +} + +// Property Decorator +function MinLength(length: number) { + return function(target: any, propertyName: string) { + let value: string; + + const getter = () => value; + const setter = (newVal: string) => { + if (newVal.length < length) { + throw new Error(`${propertyName} must be at least ${length} chars`); + } + value = newVal; + }; + + Object.defineProperty(target, propertyName, { + get: getter, + set: setter + }); + }; +} + +class User { + @MinLength(3) + username: string; +} + +/*************************** +------------ 14: Configuration ----------- +*******************************/ + +// tsconfig.json +/* +{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "lib": ["ES2020", "DOM"], + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "sourceMap": true, + "declaration": true, + "removeComments": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noUnusedLocals": true, + "noUnusedParameters": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} +*/ + +// Compiler Options Quick Reference +// --target: ES5, ES6, ES2017, ES2018, ES2019, ES2020, ESNext +// --module: commonjs, amd, es2015, es2020, esnext, system, umd +// --lib: ES5, ES6, ES2017, DOM, WebWorker, ScriptHost +// --strict: Enable all strict type checking options + +/*************************** +------------ 15: Common Patterns ----------- +*******************************/ + +// API Response Type +interface ApiResponse { + data: T; + status: number; + message: string; +} + +// Event Handler Pattern +type EventHandler = (event: T) => void; +const onClick: EventHandler = (e) => console.log(e.clientX); + +// Builder Pattern +class QueryBuilder { + private query = ""; + + select(fields: string): this { + this.query += `SELECT ${fields} `; + return this; + } + + from(table: string): this { + this.query += `FROM ${table} `; + return this; + } + + build(): string { + return this.query.trim(); + } +} + +// Factory Pattern +interface Shape { area(): number; } +class Circle implements Shape { + constructor(private radius: number) {} + area(): number { return Math.PI * this.radius ** 2; } +} + +class ShapeFactory { + static createCircle(radius: number): Shape { + return new Circle(radius); + } +} + +// Promise/Async Patterns +type AsyncResult = Promise; + +async function fetchUser(id: number): Promise { + try { + const response = await fetch(`/api/users/${id}`); + return await response.json(); + } catch { + return null; + } +} + +// Type-safe Environment Variables +interface Env { + NODE_ENV: "development" | "production" | "test"; + PORT: number; + DATABASE_URL: string; +} + +declare global { + namespace NodeJS { + interface ProcessEnv extends Env {} + } +} + +/* + * QUICK TIPS + * ---------- + * • Use 'unknown' instead of 'any' when possible + * • Prefer 'interface' for object shapes, 'type' for unions/computed types + * • Enable strict mode in tsconfig.json + * • Use const assertions: const colors = ['red', 'blue'] as const + * • Prefer type guards over type assertions + * • Use utility types instead of manual type manipulation + * • Enable noImplicitAny for better type safety + * • Use discriminated unions for complex state management + */ diff --git a/languages/typescript.md b/languages/typescript.md new file mode 100644 index 0000000..47fdfb1 --- /dev/null +++ b/languages/typescript.md @@ -0,0 +1,815 @@ +# TypeScript + +* TypeScript is a statically typed superset of JavaScript that compiles to plain JavaScript + +* It adds optional static type definitions to JavaScript, enabling better tooling and error detection + +* In TypeScript, types are checked at compile-time, not runtime + +* A TypeScript file has an extension of .ts (or .tsx for React components) + +* TypeScript follows JavaScript syntax but adds type annotations and advanced features + +* We can compile and run a TypeScript file by the following commands: + + `$ tsc filename.ts` (compile to JavaScript) + `$ node filename.js` (run the compiled JavaScript) + + Or directly: `$ ts-node filename.ts` + +#### TypeScript requires compilation to JavaScript before execution. + +## Create and execute a program + +1. Install TypeScript globally: `npm install -g typescript` +1. Create the program: `touch program.ts` +1. Write the TypeScript code and save it +1. Compile: `tsc program.ts` +1. Run: `node program.js` + +
+ +### Basic Data Types + +| Data Type | Description | Example | +| --------- | ----------- | ------- | +| number | Integer and floating point values | `42`, `3.14`, `-7` | +| string | Text values | `"hello"`, `'world'`, `` `template` `` | +| boolean | True/false values | `true`, `false` | +| undefined | Undefined value | `undefined` | +| null | Null value | `null` | +| any | Any type (disables type checking) | Can be anything | +| unknown | Type-safe counterpart of any | Requires type checking | +| void | Absence of any type | Function return type | +| never | Type that never occurs | Functions that throw errors | +| object | Non-primitive types | `{}`, `[]`, functions | + +
+ +## Keywords and Reserved Words +
+ +- TypeScript includes all JavaScript keywords plus additional TypeScript-specific ones + +| Keyword | Description | Category | +|---------- | ---------- | --------- | +| let | Declares a block-scoped variable | Variable Declaration | +| const | Declares a block-scoped constant | Variable Declaration | +| var | Declares a function-scoped variable | Variable Declaration | +| function | Declares a function | Function | +| class | Declares a class | Class | +| interface | Declares an interface | Type Definition | +| type | Declares a type alias | Type Definition | +| enum | Declares an enumeration | Type Definition | +| namespace | Declares a namespace | Module System | +| module | Declares a module | Module System | +| import | Imports from another module | Module System | +| export | Exports from current module | Module System | +| extends | Class/interface inheritance | Inheritance | +| implements | Class implements interface | Inheritance | +| public | Public access modifier | Access Modifier | +| private | Private access modifier | Access Modifier | +| protected | Protected access modifier | Access Modifier | +| readonly | Read-only property | Access Modifier | +| static | Static class member | Class Member | +| abstract | Abstract class/method | Class | +| async | Asynchronous function | Async Programming | +| await | Awaits a promise | Async Programming | +| new | Creates new instance | Object Creation | +| this | Current object reference | Object Reference | +| super | Parent class reference | Inheritance | +| typeof | Gets type of variable | Type Operation | +| keyof | Gets keys of type | Type Operation | +| in | Property existence check | Type Guard | +| instanceof | Instance type check | Type Guard | +| as | Type assertion | Type Assertion | +| is | Type predicate | Type Guard | +| infer | Infers type in conditional types | Advanced Types | +| declare | Ambient declarations | Declaration | +| get | Property getter | Accessor | +| set | Property setter | Accessor | +| yield | Generator yield | Generator | + +
+ +## Operators + +
+ +| Operator | Description | +|-|-| +| ( ) | Grouping, function call, type assertion | +| [ ] | Array indexing, array/tuple types | +| . | Property access | +| ?. | Optional chaining | +| ! | Non-null assertion, logical not | +| ~ | Bitwise not | +| \- | Unary minus, arithmetic subtraction | +| \+ | Unary plus, arithmetic addition | +| \* | Multiplication | +| / | Division | +| % | Modulo | +| \*\* | Exponentiation | +| << | Left shift | +| \>> | Right shift | +| \>>> | Unsigned right shift | + | < | Less than | +| <= | Less than or equal | +| \> | Greater than | +| \>= | Greater than or equal | +| == | Equality (with coercion) | +| === | Strict equality | +| != | Inequality (with coercion) | +| !== | Strict inequality | +| & | Bitwise AND | +| ^ | Bitwise XOR | +| \| | Bitwise OR, Union types | +| && | Logical AND | +| \|\| | Logical OR | +| ?? | Nullish coalescing | +| ? : | Ternary conditional | +| = | Assignment | +| += | Add and assign | +| -= | Subtract and assign | +| *= | Multiply and assign | +| /= | Divide and assign | +| %= | Modulo and assign | +| **= | Exponentiate and assign | +| <<= | Left shift and assign | +| \>>= | Right shift and assign | +| &= | Bitwise AND and assign | +| ^= | Bitwise XOR and assign | +| \|= | Bitwise OR and assign | +| , | Comma operator | +| => | Arrow function | +| ... | Spread/rest operator | + +### Basic Data Structures + +### Array + +- Array is an ordered collection of elements of the same or different types. + +- Arrays are created using square brackets or Array constructor: + +```typescript +let numbers: number[] = [1, 2, 3, 4]; +let fruits: Array = ["apple", "banana", "cherry"]; +let mixed: (string | number)[] = [1, "two", 3]; +``` + +- Array elements are indexed starting from 0. + +- Arrays are mutable - you can change, add, and remove elements. + +- Common array methods: +```typescript +let arr = [1, 2, 3]; +arr.push(4); // Add to end: [1, 2, 3, 4] +arr.pop(); // Remove from end: [1, 2, 3] +arr.unshift(0); // Add to start: [0, 1, 2, 3] +arr.shift(); // Remove from start: [1, 2, 3] +arr.length; // Get length: 3 +``` + +### Tuple + +- Tuple is an array with a fixed number of elements of specific types. + +- Tuples are created using square brackets with type annotations: +```typescript +let person: [string, number] = ["John", 30]; +let coordinate: [number, number] = [10, 20]; +``` + +- Tuple elements are ordered and have specific types at each position. + +- You can access elements by index, but type checking ensures correctness: +```typescript +let point: [number, number] = [10, 20]; +console.log(point[0]); // 10 (number) +console.log(point[1]); // 20 (number) +``` + +- Named tuples provide better readability: +```typescript +let user: [name: string, age: number] = ["Alice", 25]; +``` + +- Optional and rest elements in tuples: +```typescript +let optional: [string, number?] = ["hello"]; +let rest: [string, ...number[]] = ["coords", 1, 2, 3]; +``` + +### Set + +- Set is a collection of unique values of any type. + +- Sets are created using the Set constructor: +```typescript +let uniqueNumbers = new Set([1, 2, 3, 2]); // {1, 2, 3} +let stringSet = new Set(); +``` + +- Set operations: +```typescript +let mySet = new Set(); +mySet.add("apple"); // Add element +mySet.has("apple"); // Check existence: true +mySet.delete("apple"); // Remove element +mySet.clear(); // Remove all elements +mySet.size; // Get size +``` + +- Iterating over Set: +```typescript +let fruits = new Set(["apple", "banana", "cherry"]); +for (let fruit of fruits) { + console.log(fruit); +} +``` + +### Map + +- Map is a collection of key-value pairs where keys can be any type. + +- Maps are created using the Map constructor: +```typescript +let userMap = new Map(); +let mixedMap = new Map(); +``` + +- Map operations: +```typescript +let map = new Map(); +map.set("age", 30); // Add key-value pair +map.get("age"); // Get value: 30 +map.has("age"); // Check key exists: true +map.delete("age"); // Remove key-value pair +map.clear(); // Remove all entries +map.size; // Get size +``` + +- Object vs Map: +```typescript +// Object - string/symbol keys only +let obj: { [key: string]: number } = { "age": 30 }; + +// Map - any type keys +let map = new Map(); +map.set("age", 30); +map.set(42, 100); +map.set(true, 1); +``` + +### Object Types and Interfaces + +- Objects store key-value pairs and are fundamental to TypeScript. + +- Object type annotation: +```typescript +let person: { name: string; age: number } = { + name: "John", + age: 30 +}; +``` + +- Interface definition for better reusability: +```typescript +interface User { + readonly id: number; // Read-only property + name: string; + age?: number; // Optional property + [key: string]: any; // Index signature +} + +let user: User = { + id: 1, + name: "Alice" +}; +``` + +- Nested objects and complex types: +```typescript +interface Address { + street: string; + city: string; + country: string; +} + +interface Person { + name: string; + address: Address; + hobbies: string[]; +} +``` + +### Conditional branching + +```typescript +// If-else statements +if (condition) { + // code block +} else if (anotherCondition) { + // code block +} else { + // code block +} + +// Ternary operator +let result = condition ? valueIfTrue : valueIfFalse; + +// Switch statement +switch (variable) { + case value1: + // code + break; + case value2: + // code + break; + default: + // code + break; +} +``` + +### Loops + +TypeScript supports all JavaScript loop constructs: + +#### For loop +```typescript +// Traditional for loop +for (let i = 0; i < 5; i++) { + console.log(i); +} + +// For-of loop (iterates over values) +let fruits = ["apple", "banana", "cherry"]; +for (let fruit of fruits) { + console.log(fruit); +} + +// For-in loop (iterates over keys/indices) +for (let index in fruits) { + console.log(index, fruits[index]); +} +``` + +#### While loop +```typescript +let i = 0; +while (i < 5) { + console.log(i); + i++; +} + +// Do-while loop +let j = 0; +do { + console.log(j); + j++; +} while (j < 5); +``` + +#### Loop control +```typescript +for (let i = 0; i < 10; i++) { + if (i === 3) continue; // Skip iteration + if (i === 7) break; // Exit loop + console.log(i); +} +``` + +### Function definition + +```typescript +// Function declaration +function functionName(param1: type, param2: type): returnType { + return value; +} + +// Function expression +const functionName = function(param: type): returnType { + return value; +}; + +// Arrow function +const functionName = (param: type): returnType => { + return value; +}; + +// Arrow function (concise) +const functionName = (param: type): returnType => value; +``` + +### Function variations + +```typescript +// Optional parameters +function greet(name: string, age?: number): string { + return age ? `Hello ${name}, you are ${age}` : `Hello ${name}`; +} + +// Default parameters +function multiply(a: number, b: number = 1): number { + return a * b; +} + +// Rest parameters +function sum(...numbers: number[]): number { + return numbers.reduce((total, num) => total + num, 0); +} + +// Function overloads +function process(input: string): string; +function process(input: number): number; +function process(input: string | number): string | number { + if (typeof input === 'string') { + return input.toUpperCase(); + } + return input * 2; +} + +// Generic functions +function identity(arg: T): T { + return arg; +} + +let result = identity("hello"); // Type is string +let result2 = identity(42); // Type inferred as number +``` + +### Function call + +```typescript +functionName(argument1, argument2); + +// With optional parameters +greet("John"); // "Hello John" +greet("John", 25); // "Hello John, you are 25" + +// With rest parameters +sum(1, 2, 3, 4); // 10 + +// Generic function call +identity("hello"); +identity(42); // Type inferred +``` + +### Classes + +```typescript +class ClassName { + // Properties + public publicProperty: type; + private privateProperty: type; + protected protectedProperty: type; + readonly readonlyProperty: type; + static staticProperty: type; + + // Constructor + constructor(param: type) { + this.publicProperty = param; + } + + // Methods + public method(): returnType { + return value; + } + + // Getters and setters + get property(): type { + return this.privateProperty; + } + + set property(value: type) { + this.privateProperty = value; + } + + // Static method + static staticMethod(): returnType { + return value; + } +} + +// Inheritance +class ChildClass extends ParentClass { + constructor(param: type) { + super(param); // Call parent constructor + } + + // Override method + method(): returnType { + return super.method(); // Call parent method + } +} + +// Abstract class +abstract class AbstractClass { + abstract abstractMethod(): void; + + concreteMethod(): void { + console.log("This is implemented"); + } +} +``` + +### Key TypeScript Features + +* **Static Typing**: Types are checked at compile-time +* **Type Inference**: TypeScript can often infer types automatically +* **Optional Typing**: You can gradually add types to existing JavaScript +* **Generics**: Create reusable components that work with multiple types +* **Interfaces**: Define contracts for objects and classes +* **Enums**: Create named constants +* **Union Types**: Variables can be one of several types +* **Intersection Types**: Combine multiple types +* **Type Guards**: Runtime type checking +* **Decorators**: Add metadata to classes and methods + +### Compilation + +* TypeScript code must be compiled to JavaScript before execution +* The TypeScript compiler (`tsc`) performs type checking and transpilation +* Configuration is managed through `tsconfig.json` +* TypeScript can target different JavaScript versions (ES5, ES6, etc.) +* Source maps can be generated for debugging compiled code + +#### Sample TypeScript Code + +**hello.ts** +```typescript +// TypeScript source code +interface User { + name: string; + age: number; + isActive?: boolean; +} + +class UserManager { + private users: User[] = []; + + addUser(user: User): void { + this.users.push(user); + console.log(`Added user: ${user.name}`); + } + + getActiveUsers(): User[] { + return this.users.filter(user => user.isActive ?? true); + } + + getUserCount(): number { + return this.users.length; + } +} + +// Generic function +function processData(data: T[], processor: (item: T) => T): T[] { + return data.map(processor); +} + +// Usage +const userManager = new UserManager(); + +const newUser: User = { + name: "John Doe", + age: 30, + isActive: true +}; + +userManager.addUser(newUser); + +// Arrow functions with types +const formatUser = (user: User): string => + `${user.name} (${user.age} years old)`; + +// Union types and type guards +function displayInfo(value: string | number | boolean): string { + if (typeof value === "string") { + return `Text: ${value.toUpperCase()}`; + } else if (typeof value === "number") { + return `Number: ${value.toFixed(2)}`; + } else { + return `Boolean: ${value ? "Yes" : "No"}`; + } +} + +console.log(displayInfo("hello")); +console.log(displayInfo(42.567)); +console.log(displayInfo(true)); +``` + +#### Compilation Commands + +```bash +# Compile single file +tsc hello.ts + +# Compile with specific target +tsc hello.ts --target ES2020 + +# Compile with source maps +tsc hello.ts --sourceMap + +# Watch mode (recompile on changes) +tsc hello.ts --watch + +# Compile all files in project +tsc + +# Check for errors without generating files +tsc --noEmit + +# Compile with strict mode +tsc hello.ts --strict +``` + +#### Compiled JavaScript Output + +**hello.js** (compiled from above TypeScript) +```javascript +"use strict"; +// JavaScript output (target ES2017) +class UserManager { + constructor() { + this.users = []; + } + addUser(user) { + this.users.push(user); + console.log(`Added user: ${user.name}`); + } + getActiveUsers() { + return this.users.filter(user => user.isActive ?? true); + } + getUserCount() { + return this.users.length; + } +} +// Generic function (types removed) +function processData(data, processor) { + return data.map(processor); +} +// Usage +const userManager = new UserManager(); +const newUser = { + name: "John Doe", + age: 30, + isActive: true +}; +userManager.addUser(newUser); +// Arrow functions +const formatUser = (user) => `${user.name} (${user.age} years old)`; +// Type guards remain as runtime checks +function displayInfo(value) { + if (typeof value === "string") { + return `Text: ${value.toUpperCase()}`; + } + else if (typeof value === "number") { + return `Number: ${value.toFixed(2)}`; + } + else { + return `Boolean: ${value ? "Yes" : "No"}`; + } +} +console.log(displayInfo("hello")); +console.log(displayInfo(42.567)); +console.log(displayInfo(true)); +``` + +#### tsconfig.json Configuration + +```json +{ + "compilerOptions": { + // Basic Options + "target": "ES2020", // Target JavaScript version + "module": "commonjs", // Module system + "lib": ["ES2020", "DOM"], // Include library files + "outDir": "./dist", // Output directory + "rootDir": "./src", // Input directory + "strict": true, // Enable strict type checking + + // Additional Checks + "noUnusedLocals": true, // Error on unused variables + "noUnusedParameters": true, // Error on unused parameters + "noImplicitReturns": true, // Error on missing return statements + "noFallthroughCasesInSwitch": true, // Error on fallthrough cases + + // Module Resolution + "moduleResolution": "node", // Module resolution strategy + "baseUrl": "./", // Base directory + "paths": { // Path mapping + "@/*": ["src/*"], + "@utils/*": ["src/utils/*"] + }, + + // Source Maps & Debugging + "sourceMap": true, // Generate source maps + "inlineSourceMap": false, // Don't inline source maps + "declaration": true, // Generate .d.ts files + "declarationMap": true, // Generate .d.ts.map files + + // Experimental + "experimentalDecorators": true, // Enable decorators + "emitDecoratorMetadata": true, // Emit decorator metadata + + // JavaScript Support + "allowJs": true, // Allow JavaScript files + "checkJs": false, // Type check JavaScript files + + // Other Options + "esModuleInterop": true, // CommonJS/ES6 interop + "skipLibCheck": true, // Skip lib.d.ts type checking + "forceConsistentCasingInFileNames": true, // Consistent file names + "removeComments": true, // Remove comments from output + "noEmitOnError": true // Don't emit if there are errors + }, + "include": [ + "src/**/*", // Include all files in src + "tests/**/*" // Include test files + ], + "exclude": [ + "node_modules", // Exclude node_modules + "dist", // Exclude output directory + "**/*.test.ts", // Exclude test files from compilation + "**/*.spec.ts" + ], + "files": [ + // Explicitly include specific files (optional) + "src/main.ts" + ] +} +``` + +#### Package.json Scripts + +```json +{ + "name": "typescript-project", + "version": "1.0.0", + "scripts": { + "build": "tsc", + "start": "node dist/main.js", + "dev": "ts-node src/main.ts", + "watch": "tsc --watch", + "clean": "rm -rf dist", + "type-check": "tsc --noEmit" + }, + "devDependencies": { + "typescript": "^4.9.0", + "ts-node": "^10.9.0", + "@types/node": "^18.0.0" + } +} +``` + +#### Compilation Examples with Different Targets + +**Original TypeScript:** +```typescript +const greet = (name: string = "World"): string => `Hello, ${name}!`; +const user = { name: "Alice", age: 30 }; +const { name, age } = user; +``` + +**Compiled to ES5:** +```javascript +var greet = function (name) { + if (name === void 0) { name = "World"; } + return "Hello, " + name + "!"; +}; +var user = { name: "Alice", age: 30 }; +var name = user.name, age = user.age; +``` + +**Compiled to ES2020:** +```javascript +const greet = (name = "World") => `Hello, ${name}!`; +const user = { name: "Alice", age: 30 }; +const { name, age } = user; +``` + +#### Error Examples + +**TypeScript with errors:** +```typescript +// Type errors that prevent compilation +let message: string = 42; // Error: Type 'number' is not assignable to type 'string' +let numbers: number[] = ["a", "b"]; // Error: Type 'string' is not assignable to type 'number' + +function add(a: number, b: number): number { + return a + b; +} + +add("hello", "world"); // Error: Argument of type 'string' is not assignable to parameter of type 'number' +``` + +**Compiler output:** +```bash +$ tsc error-example.ts +error-example.ts(2,5): error TS2322: Type 'number' is not assignable to type 'string'. +error-example.ts(3,5): error TS2322: Type 'string[]' is not assignable to type 'number[]'. +error-example.ts(8,5): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +```