TypeScript Basics

Learn the basics of Typescript, including data types, functions, classes, interfaces, aliases, and type checking.

Data types

TypeScript has several basic data types. Let’s discuss some of them below:

  • Number: A number can be either an integer or a floating-point number.

  • String: Strings represent text data in TypeScript. They can be enclosed in single quotes (') or double quotes ("). TypeScript supports various string operations and methods like concatenation, substring, etc.

  • Boolean: Booleans represent logical values true or false. They are commonly used for conditional expressions and control flow.

Press + to interact
// Number
let num: number = 15;
console.log("num:", num); // Output: num: 15
let pi: number = 3.14;
console.log("pi:", pi); // Output: pi: 3.14
// String
let str: string = "TypeScript";
console.log("str:", str); // Output: str: TypeScript
// Boolean
let condition: boolean = true;
console.log("condition:", condition); // Output: condition: true

Let’s discuss some other types of data types supported in TypeScript:

  • Array: Arrays in TypeScript are homogeneous collections of elements, meaning they can only contain elements of the same type.

  • Tuple: Tuples are arrays with a fixed number of elements, each potentially of a different type. They allow us to express an array where the type of a fixed number of elements is known but not necessarily all elements.

  • Enums: Enums are a way to give more friendly names to sets of numeric values. By default, enums begin numbering their members starting from 0, but we can also customize the start value or assign values explicitly.

  • null or undefined: In TypeScript, null and undefined are subtypes of all other types, meaning we can assign them to variables of any type.

  • void: The void is used as the return type of functions that do not return a value. It is the absence of any type. Variables of type void can only be assigned undefined or null.

The any type allows us to opt out of type checking. It can represent any value and is useful when working with dynamic content or when migrating existing JavaScript code to TypeScript.

Press + to interact
// Arrays
let colors:string[] = new Array("red","green", "blue");
console.log("colors array:", colors); // Output: colors array: [ 'red', 'green', 'blue' ]
// Tuple
let tuple: [string, number] = ["hello", 10];
console.log("\ntuple:", tuple); // Output: tuple: [ 'hello', 10 ]
// Enums
enum Direction {
Up,
Down,
Left,
Right,
}
console.log("\nDirection enum:", Direction);
/* Output: Direction enum: {
'0': 'Up',
'1': 'Down',
'2': 'Left',
'3': 'Right',
Up: 0,
Down: 1,
Left: 2,
Right: 3
} */
// Null and undefined
let n: null = null;
console.log("\nnull variable n:", n); // Output: null variable n: null
let u: undefined = undefined;
console.log("undefined variable u:", u); // Output: undefined variable u: undefined
// Any
let variable: any = 4;
console.log("\nvariable:", variable); // Output: variable: 4
variable = "maybe a string instead";
console.log("updated value of variable:", variable); // Output: updated value of variable: 4

Functions

Functions in TypeScript can have parameters and return types annotated with types, allowing for type safety and better documentation.

Press + to interact
// Function with parameters and return type annotation
function add(x: number, y: number): number {
return x + y;
}
console.log(add(5, 3)); // Output: 8

TypeScript supports optional parameters, default parameters, rest parameters, and function overloading. Let’s discuss them in detail.

Optional parameters

Optional parameters are parameters that may or may not be provided when calling a function. They are denoted by adding a question mark (?) after the parameter name in the function declaration. If an optional parameter is not provided during the function call, its value becomes undefined.

Press + to interact
// Optional parameter
function greet(name: string, greeting?: string): void {
if (greeting) {
console.log(`${greeting}, ${name}!`);
} else {
console.log(`Hello, ${name}!`);
}
}
greet("Alice"); // Output: Hello, Alice!
greet("Bob", "Hi"); // Output: Hi, Bob!

Default parameters

The default parameter allows to specify default values for parameters in case they are not provided during the function call. Default parameters are indicated by assigning a value to the parameter in the function declaration.

Press + to interact
// Default parameter
function say(message: string = "Hello"): void {
console.log(message);
}
say(); // Output: Hello
say("Goodbye"); // Output: Goodbye

Rest parameters

The rest parameter allows to represent an indefinite number of arguments as an array. They are denoted by prefixing the parameter name with three dots (...). Rest parameters gather the remaining arguments into an array.

Press + to interact
// Rest parameter
function sum(...numbers: number[]): number {
return numbers.reduce((acc, curr) => acc + curr, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // Output: 15

Function overloading

Function overloading allows to define multiple function signatures for a single function name. TypeScript selects the appropriate function signature based on the number and types of arguments provided during the function call.

Press + to interact
// Function overloading
function display(value: string): void;
function display(value: number): void;
function display(value: any): void {
console.log(`Value is: ${value}`);
}
display("Hello"); // Output: Value is: Hello
display(42); // Output: Value is: 42

Classes

Classes in TypeScript allow to implement the object-oriented programming concepts such as inheritance, encapsulationEncapsulation refers to bundling data (attributes) and methods (functions) that operate on the data within a single unit (class). It restricts direct access to the data from outside the class and encourages the use of getter and setter methods to interact with the data, thus hiding the internal implementation details and providing better control over data manipulation., and abstractionAbstraction is the process of hiding the complex implementation details and showing only the necessary features of an object to the outside world.. Classes in TypeScript also support the following:

  • Constructors: Constructors are special methods that are automatically called when a class instance is created.

  • Properties: Properties are variables that belong to a class and define the state or characteristics of the objects created from that class.

  • Methods: Methods are functions that are defined within a class and can perform actions or calculate values based on the object’s state.

  • Inheritance: Inheritance allows a class (subclass/derived class) to inherit properties and behavior (methods) from another class (superclass/base class).

  • Access modifiers: Access modifiers control the visibility and accessibility of class members (properties and methods).

    • public: Members are accessible from outside the class.

    • private: Members are accessible only within the class that defines them.

    • protected: Members are accessible within the class and its subclasses.

Press + to interact
// Class
class Person {
// Properties
firstName: string;
lastName: string;
// Constructor
constructor(firstName: string, lastName: string) {
this.firstName = firstName;
this.lastName = lastName;
}
// Method
fullName(): string {
return `${this.firstName} ${this.lastName}`;
}
}
const person = new Person("Alice", "Female");
console.log(person.fullName()); // Output: Alice Female

Interfaces

Interfaces define contracts in TypeScript, specifying the structure that an object must adhere to. They can include properties, methods, and index signaturesIndex signatures, also known as indexable types, allow to define the types of properties that can be accessed using an index (typically a string or a number) in TypeScript. They are useful when we want to define objects that act like dictionaries or maps, where we can access properties dynamically by their keys.. Interfaces promote code reusability, maintainability and provide compile-time checks for object shapes.

Press + to interact
// Interface defining the structure of a Person object
interface Person {
firstName: string;
lastName: string;
age: number;
greet(): string;
}
// Implementing the Person interface
class Student implements Person {
constructor(public firstName: string, public lastName: string, public age: number) {}
greet(): string {
return `Hello, my name is ${this.firstName} ${this.lastName} and I'm ${this.age} years old.`;
}
}
const student = new Student("Alice", "Bob", 20);
console.log(student.greet());
// Output: Hello, my name is Alice Bob and I'm 20 years old.

Type aliases

Type aliases allow to create custom names for types. They are especially useful for complex types like union types, intersection types, tuple types, and more. Type aliases enhance code readability and maintainability by providing descriptive names for types.

Press + to interact
// Type alias for a complex number
type ComplexNumber = {
real: number;
imaginary: number;
};
// Function using the ComplexNumber type alias
function addComplex(a: ComplexNumber, b: ComplexNumber): ComplexNumber {
return {
real: a.real + b.real,
imaginary: a.imaginary + b.imaginary
};
}
// Usage of the addComplex function
const result = addComplex({ real: 1, imaginary: 2 }, { real: 3, imaginary: 4 });
console.log(result); // Output: { real: 4, imaginary: 6 }

Type checking

TypeScript performs static type checking, which means type errors are caught at compile-time rather than runtime. It helps identify bugs early in the development process, improves code quality, and facilitates refactoring. TypeScript’s type system is powerful and expressive, supporting type inference, type assertions, type guards, and more.

Press + to interact
let message: string = "hello";
message = 42; // Error: Type 'number' is not assignable to type 'string'.

We can see the error in the playground above that we can’t assign the number value to a string variable.