Learning TypeScript
Intro and Setup for Typescript
Superset of Javascript, its built on top of JS
JS is a dynamically typed language, where we dont define the types and they are associated with run-time also like python whereas, TypeScript is a statically typed language, you define types to variable like , C , java
You need to compile Typescript to work for your case, it compiles .ts to .js and
Learning typescript
let id = 5; // js
let id: number = 5; // typescript
Here we defined a type and as the modern browsers can only understand JS and no this fancy languages so we need to compile this to JS.
To convert to JS we use tsc, that is typescript compiler
tsc index.ts : This compiles the index.tsc file to index.js file
Create at typescript config file, using tsc --init
This creates a file named tsconfig.json, that contains all the confs for your .ts file, where you mention the root directory , the source directory , javascript version to compile to .. etc
tsc --watch : watches for all tsc files and auto compiles them in the destination directory mentioned
Data-Types and Usage in Typescript
// All PRIMITIVE TYPES in typescript
// string: Textual data (e.g., "hello").
// number: Numeric values (integer, float, hexadecimal, etc.).
// boolean: true or false.
// null: Explicit absence of a value.
// undefined: Variable not yet assigned.
// symbol: Unique, immutable identifier (e.g., Symbol('key')).
// bigint: Large integers (e.g., 100n).
// All SPECIAL TYPES in typescript
// any: Opt-out of type checking (use sparingly).
// unknown: Type-safe counterpart of any (requires type assertion before use).
// never: Represents unreachable code (e.g., function that always throws an error).
// void: Absence of a return value (common in functions, e.g., function log(): void).
let id: number = 5;
let company: string = "Traversy Media";
let isPublished: boolean = true;
let x: any = "Hello";
x = true;
let age: number
age = 50;
// Array of numbers
let ids: number[] = [1, 2, 3, 4, 5]; // ids should be a list of numbers / integers
// Array of any
let arr: any[] = [1, true, "Hello", 4, 5];
// Number , String , Boolean (tuple of 3 data types)
let user: [number, string, boolean] = [1, "Traversy", true];
let person: [number , string, boolean] = [1, "brad", true];
// Array of tuples of number and string
let employee: [number, string][]
employee = [
[1, 'hello'],
[2, 'world'],
]
// Union
let pid: string | number
pid = "12";
pid = 22;
// Enum
enum Direction1{
Up,
Down,
Left,
Right
}
enum Direction2{
Up = "Up",
Down = "Down",
Left = "Left",
Right = "Right"
}
// by default the values are 0, 1, 2, 3 in the order !!
console.log(Direction1.Up); // 0
console.log(Direction1.Down); // 1
console.log(Direction1.Left); // 2
console.log(Direction2.Up); // Up
console.log(Direction2.Down); // Down
console.log(Direction2.Left); // Left
// Objects (key-value pair) (key-name : data-type )
type User = {
id: number,
name: string
}
const user2: User = {
id: 1,
name: "John"
}
Bit complex in TypeScript
Type-Assertion : Its a way to tell the compiler, “trust me, I know what type this is”
Its a way to tell typescript, that u as developer know about its type than TypeScript’s type checker ..
// Example-1
let value: any = "hello";
let strLength: number = (<string>value).length;
//Example-2
let value: any = "hello";
let strLength: number = (value as string).length;
Overriding implicit ‘any’ types
Interesting Example
const inputElement = document.getElementById("email") as HTMLInputElement;
inputElement.value = "user@example.com"; // Now TypeScript knows it's an input
Possible types for document.getElementById(“email”) are either an HTMLElement or a null value
So a code like this :
const inputElement = document.getElementById("email");
inputElement.value = "user@example.com"; // ❌ Error: Property 'value' does not exist on type 'HTMLElement'.
So we need to do a type assertion, so if I make that to HTMLInputElement, I will tell typescript explicitly that this is not any HTMLElement its a HTMLInputElement
// Suppose the element with ID "email" is a `<div>`:
<div id="email">Hey I am Email in a div tag</div>
const inputElement = document.getElementById("email") as HTMLInputElement; // ex-1
const inputElement = <HTMLInputElement>document.getElementById("email"); // ex-2
inputElement.value = "test"; // 💥 Runtime Error: `value` property doesn't exist on `<div>`.
You can’t leave any variable untouched in typescript , the sole purpose of typescript is to be able to do better type checking.
function addNum(x: number, y: number): number{
return x+y;
}
// This defines that output is also a number
Either you have to define it as a any or void
Complete typescript with comments !
// Void
function log(message: string | number ): void {
console.log(message);
}
//Interfaces
// Interface
interface UserInterface { //
id: number,
name: string,
age?: string // This is an Optional field
readonly email?: string // This is a Readonly field
}
const user1: UserInterface = {
id: 1,
name: "John"
}
// interface inside function
interface MathFunction {
(x: number, y: number): number
}
const add2 : MathFunction = function(x: number, y: number): number {
return x + y
};
const subtract: MathFunction = (x: number, y: number): number => x-y;
// Classes
class Person{
id: number
name : string
constructor(id: number, name: string){
this.id = id;
this.name = name;
console.log("Hello World");
}
}
const mohit = new Person(21 , "Mohit");
const john = new Person(22 , "John");
mohit.id = 123;
// Public, private, protected
// protected: used inside the class and its subclasses
// This = self, in python
class Person2{
private id: number
public name: string
protected age: number
constructor(id: number, name: string, age: number){
this.id = id;
this.name = name;
this.age = age;
}
function(a: number, b: number): void{
console.log(this.id);
console.log(a+b);
}
}
// interface in a class
interface PersonInterface{
id: number,
name: string,
register(): string
}
class Person3 implements PersonInterface{ // This si just an extra type-checking and does nothing interesting ... !!
id: number
name: string
constructor(id: number, name: string){
this.id = id;
this.name = name;
}
register(){
return `${this.name} is now registered`;
}
}
// subclass
class Names extends Person3{
position : string
constructor(id: number, name: string, position: string){
super(id, name); // Take the parent class implementation of constructor and use that !
this.position = position;
}
}
// Generics
function getArray(items: any[]): any[]{
return new Array().concat(items);
}
let numArr = getArray([1,2,3,4]);
let strArray = getArray(["Hello", "World"]);
numArr.push('Mohit'); // This gives no error as its of `any` type
// How to change this ?
function getArray2<T>(items: T[]): T[]{
return new Array().concat(items);
}
let numArr2 = getArray2<number>([1,2,3,4]);
let strArray2 = getArray2<string>(["Hello", "World"]);
// numArr2.push('Mohit'); // This gives an error as its of `number` type
numArr2.push(5); // This is fine as its of `number` type
