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