Mastering TypeScript: A Comprehensive Guide
From Fundamentals to Intermediate Techniques for Effective Development
Table of contents
TypeScript is an open-source programming language developed by Microsoft that builds upon JavaScript by adding optional static typing, interfaces, classes, and other features to help developers write robust and scalable code. It compiles to plain JavaScript, making it compatible with existing JavaScript frameworks and libraries, while providing additional tooling and language features to improve developer productivity and code quality.
Beginner Level:
Understand JavaScript Fundamentals:
JavaScript fundamentals include knowledge of variables, data types, functions, objects, arrays, and control flow.
// Variables
let x = 5;
const y = "Hello";
// Data Types
let num = 10; // Number
let str = "Hello"; // String
let bool = true; // Boolean
let arr = [1, 2, 3]; // Array
let obj = { name: "sadanandgadwal", age: 23 }; // Object
// Functions
function greet(name) {
return "Hello, " + name + "!";
}
console.log(greet("sadanandgadwal")); // Output: Hello, sadanandgadwal!
// Objects
let person = {
name: "sadanandgadwal",
age: 23,
greet: function() {
return "Hello, " + this.name + "!";
}
};
console.log(person.greet()); // Output: Hello, sadanandgadwal!
1) Introduction to TypeScript:
TypeScript is a superset of JavaScript that adds optional static typing, interfaces, classes, and modules among other features.
function greet(name: string): string {
return "Hello, " + name + "!";
}
console.log(greet("sadanandgadwal")); // Output: Hello, sadanandgadwal!
interface Person {
name: string;
age: number;
}
function greetPerson(person: Person): string {
return "Hello, " + person.name + "!";
}
console.log(greetPerson({ name: "sadanandgadwal", age: 23 })); // Output: Hello, sadanandgadwal!
The
greet
function is defined, which takes aname
parameter of type string and returns a string greeting.The
greet
function is called with the argument"sadanandgadwal"
and the returned value is logged to the console.An interface named
Person
is defined, specifying that any object implementing it must have aname
property of type string and anage
property of type number.The
greetPerson
function is defined, which takes aperson
parameter of typePerson
interface and returns a string greeting.The
greetPerson
function is called with an object that satisfies thePerson
interface, and the returned value is logged to the console.
Setting Up Development Environment:
Setting up the development environment involves installing Node.js and npm and configuring a TypeScript compiler like tsc
.
# Install Node.js and npm
# Download and install from https://nodejs.org/
# Install TypeScript globally
npm install -g typescript
# Create a TypeScript file (example.ts)
# Run the TypeScript compiler to generate JavaScript
tsc example.ts
2) Basic TypeScript Syntax:
Basic TypeScript syntax includes declaring variables with types, understanding type inference, and using basic type annotations and assertions.
// Variable Declaration
let x: number = 5;
const y: string = "Hello";
// Type Inference
let num = 10;
let str = "Hello";
// Basic Type Annotations and Assertions
let z: boolean;
z = true;
// Type Assertion
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
// Alternatively, you could use angle bracket syntax: let strLength: number = (<string>someValue).length;
console.log(x); // Output: 5
console.log(y); // Output: Hello
console.log(num); // Output: 10
console.log(str); // Output: Hello
console.log(z); // Output: true
console.log(strLength); // Output: 16
The variable
x
is declared as a number and assigned the value5
.The constant
y
is declared as a string and assigned the value"Hello"
.TypeScript infers the types of variables
num
andstr
based on their initial values.The variable
z
is declared as a boolean and assigned the valuetrue
.Type assertion is used to treat
someValue
as a string in order to access itslength
property, and the result is stored instrLength
.All variables are logged to the console to demonstrate their values.
3) Functions and Interfaces:
In TypeScript, you can define function types and use interfaces to define object shapes and enforce contracts.
// Function Types
type GreetFunction = (name: string) => string;
// Declare a variable
let greet: GreetFunction = function(name: string) {
return "Hello, " + name + "!";
};
console.log(greet("sadanandgadwal")); // Output: Hello, sadanandgadwal!
// Interface
interface Person {
name: string;
age: number;
}
function greetPerson(person: Person): string {
return "Hello, " + person.name + "!";
}
console.log(greetPerson({ name: "sadanandgadwal", age: 23 })); // Output: Hello, sadanandgadwal!
A type alias
GreetFunction
is defined for a function that takes aname
parameter of typestring
and returns astring
.A variable
greet
of typeGreetFunction
is declared and assigned a function expression that matches the defined function type.The
greet
function is called with the argument"sadanandgadwal"
and the returned value is logged to the console.An interface
Person
is defined with propertiesname
of typestring
andage
of typenumber
.The
greetPerson
function is defined, which takes a parameterperson
of typePerson
interface and returns a string greeting.The
greetPerson
function is called with an object that satisfies thePerson
interface, and the returned value is logged to the console.
4) Working with Classes:
Classes and inheritance in TypeScript allow you to create blueprints for objects with methods and properties.
// Class
class Person {
name: string;
age: number;
// Define a constructor
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
greet(): string {
return "Hello, " + this.name + "!";
}
}
let person = new Person("sadanandgadwal", 23);
console.log(person.greet()); // Output: Hello, sadanandgadwal!
A class
Person
is defined with propertiesname
andage
, and a constructor function that initializes these properties when a new object is created.The class
Person
has a method namedgreet
that returns a greeting message using thename
property.A new instance of the
Person
class is created with the name "sadanandgadwal" and age 23.The
greet
method of theperson
object is called and the returned value is logged to the console.
Intermediate Level :
1) Advanced Types:
Advanced types in TypeScript include union types, intersection types, type aliases, conditional types, etc.
// Union Types
let val: number | string;
val = 10;
val = "Hello";
// Intersection Types
interface A {
propA: number;
}
interface B {
propB: string;
}
type C = A & B;
let obj: C = { propA: 10, propB: "Hello" };
// Conditional Types
type TypeName<T> = T extends string ? "string" :
T extends number ? "number" :
T extends boolean ? "boolean" :
"unknown";
let a: TypeName<string> = "string"; // Output: "string"
let b: TypeName<number> = "number"; // Output: "number"
let c: TypeName<boolean> = "boolean"; // Output: "boolean"
let d: TypeName<object> = "unknown"; // Output: "unknown"
console.log(val); // Output: Hello
console.log(obj); // Output: { propA: 10, propB: "Hello" }
console.log(a); // Output: string
console.log(b); // Output: number
console.log(c); // Output: boolean
console.log(d); // Output: unknown
A variable
val
is declared that can hold values of typenumber
orstring
.An object
obj
is declared with properties from both interfacesA
andB
, which are then assigned to a variable of typeC
, an intersection ofA
andB
.Conditional types are used to define a type
TypeName<T>
that returns different strings based on the type ofT
.Variables
a
,b
,c
, andd
are declared with different type arguments forTypeName
and assigned values accordingly.All variables are logged to the console to demonstrate their values.
2) Generics:
Generics allow you to write reusable, type-safe functions, interfaces, and classes.
// Generic Function
function identity<T>(arg: T): T {
return arg;
}
let num: number = identity(10); // Output: 10
let str: string = identity("Hello"); // Output: "Hello"
// Generic Interface
interface Box<T> {
value: T;
}
let box: Box<number> = { value: 10 };
// Generic Class
class Pair<T, U> {
constructor(public first: T, public second: U) {}
}
let pair: Pair<number, string> = new Pair(10, "Hello");
console.log(num); // Output: 10
console.log(str); // Output: Hello
console.log(box); // Output: { value: 10 }
console.log(pair); // Output: Pair { first: 10, second: "Hello" }
A generic function
identity
is defined that takes an argumentarg
of typeT
and returns the same typeT
.The
identity
function is called with a number and a string, and the returned values are assigned to variablesnum
andstr
respectively.A generic interface
Box<T>
is defined with a single propertyvalue
of typeT
.A variable
box
of typeBox<number>
is created with a value property of type number.A generic class
Pair<T, U>
is defined with two propertiesfirst
of typeT
andsecond
of typeU
.An instance
pair
of thePair<number, string>
class is created with values 10 and "Hello".All variables are logged to the console to demonstrate their values.
3) Modules and Namespaces:
Modules in TypeScript allow you to organize code into reusable units. Namespaces provide a way to logically group related code.
// math.ts
export function sum(a: number, b: number): number {
return a + b;
}
// app.ts
import { sum } from "./math";
console.log(sum(2, 3)); // Output: 5
// namespace
namespace Math {
export function sum(a: number, b: number): number {
return a + b;
}
}
// app.ts
/// <reference path="math.ts" />
console.log(Math.sum(2, 3)); // Output: 5
The
math.ts
file defines a functionsum
in the modulemath
that takes two numbers and returns their sum.In
app.ts
, thesum
function is imported from themath
module using theimport
statement, and the result ofsum(2, 3)
is logged to the console.A namespace
Math
is defined inmath.ts
containing a functionsum
that calculates the sum of two numbers.In
app.ts
, thesum
function from theMath
namespace is used by referencing themath.ts
file using/// <reference path="math.ts" />
, and the result ofMath.sum(2, 3)
is logged to the console.
4) Decorators:
Decorators are a feature of TypeScript that allow you to attach metadata to classes, methods, and properties.
// Class Decorator
function Logged(target: Function) {
console.log("Class logged:", target);
}
//'MyClass' class.
@Logged
class MyClass {}
// Method Decorator
function Log(target: any, key: string, descriptor: PropertyDescriptor) {
console.log("Method logged:", key);
}
// Define a class 'MyService'.
class MyService {
@Log
getData() {}
}
// Property Decorator
function Configurable(value: boolean) {
return function(target: any, propertyKey: string) {
Object.defineProperty(target, propertyKey, {
configurable: value
});
};
}
// Define a class 'MyComponent'.
class MyComponent {
@Configurable(false)
apiUrl = "https://example.com";
}
// Console output
console.log(MyClass);
new MyService().getData();
console.log(Object.getOwnPropertyDescriptor(MyComponent.prototype, "apiUrl"));
A class decorator
Logged
is defined that logs a message when applied to a class.The
Logged
decorator is applied to theMyClass
class, resulting in a log message when the class is defined.A method decorator
Log
is defined that logs a message when applied to a method.The
Log
decorator is applied to thegetData
method of theMyService
class, resulting in a log message when the method is accessed.A property decorator factory
Configurable
is defined that returns a property decorator function.The
Configurable
decorator is applied to theapiUrl
property of theMyComponent
class, setting itsconfigurable
property tofalse
.Console output shows the log messages and the property descriptor for the
apiUrl
property.
5) Error Handling:
Understanding how TypeScript handles errors and exceptions, including synchronous and asynchronous error handling strategies.
// Synchronous Error Handling
function divide(x: number, y: number): number {
if (y === 0) {
throw new Error("Division by zero");
}
return x / y;
}
//try-catch block
try {
console.log(divide(10, 0)); // Output: Error: Division by zero
} catch (error) {
console.error(error.message);
}
// Asynchronous Error Handling
async function fetchData() {
try {
let response = await fetch("https://example.com/data");
if (!response.ok) {
throw new Error("Failed to fetch data");
}
let data = await response.json();
console.log(data);
} catch (error) {
console.error(error.message);
}
}
fetchData();
The
divide
function is defined to divide two numbers and throw an error if the second number is zero.A try-catch block is used to handle errors that may occur during the execution of the
divide
function.An asynchronous function
fetchData
is defined to fetch data from a remote URL usingfetch
.The
fetchData
function uses a try-catch block to handle errors that may occur during the fetch operation or parsing of the response.The
fetchData
function is called to initiate the asynchronous data fetching process. Any errors that occur are logged to the console.
Conclusion
This guide covered TypeScript essentials, from syntax to advanced features like generics and decorators. Error handling strategies and integration with frameworks were explored. Mastering TypeScript empowers developers to create scalable, organized codebases, contributing effectively to modern web development projects.
Playground for Typescript
Playcode.io is an online code editor and playground that allows users to write, edit, and execute HTML, CSS, and JavaScript code and even Typescript.
🌟 Stay Connected! 🌟
Hey there, awesome reader! 👋 Want to stay updated with my latest insights,Follow me on social media!