TypeScript
TS01 / TS02

TS01 / TS02 Exercises

Practical Exercises

  1. Write a function sum that takes two numbers and returns their sum.
function sum(a: number, b: number): number {
    return a + b;
}
  1. Write a function filterEvenNumbers that takes an array of numbers as an argument and returns a new array containing only the even numbers.
function filterEvenNumbers(numbers: number[]): number[] {
    return numbers.filter(number => number % 2 === 0);
}
  1. Write a function named printUser that takes an object of type User which has the properties name, email, and age as an argument and prints the user to the console.
type User = {
    name: string;
    email: string;
    age: number;
};
 
function printUser(user: User): void {
console.log(user);
}
 
  1. Write a function named getWords that takes an argument of type string | string[]. If the input is a string, it should split the string by spaces and return the resulting array. If the input is already an array, it should return the array as is.
function getWords(input: string | string[]): string[] {
    return typeof input === 'string' ? input.split(' ') : input;
}
  1. Write a function toNumber that takes an argument of type number | string | boolean.
function toNumber(value: number | string | boolean): number {
    if (typeof value === 'number') {
        return value;
    } else if (typeof value === 'string') {
        const number = parseFloat(value);
        if (isNaN(number)) throw new Error('Cannot convert string to number');
        return number;
    } else {
        return value ? 1 : 0;
    }
}
  1. Write a function validateInput that takes a union type argument of string | undefined.
function validateInput(input: string | undefined): boolean {
    return typeof input === 'string' && input.length > 5;
}
  1. Create a literal union type named Direction which can only be one of the following values: "North", "South", "East", "West".
type Direction = "North" | "South" | "East" | "West";
 
function move(point: { x: number, y: number }, direction: Direction): { x: number, y: number } {
switch (direction) {
case "North": return { ...point, y: point.y + 1 };
case "South": return { ...point, y: point.y - 1 };
case "East": return { ...point, x: point.x + 1 };
case "West": return { ...point, x: point.x - 1 };
default: return point;
}
}
 
  1. Create a literal union type Day containing the possible days of the week.
type Day = "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | "Sunday";
 
function isWeekend(day: Day): boolean {
    return day === "Saturday" || day === "Sunday";
}
  1. Create a type for a Circle and a Rectangle.
type Circle = {
    kind: "circle";
    radius: number;
};
 
type Rectangle = {
kind: "rectangle";
width: number;
height: number;
};
 
function calculateArea(shape: Circle | Rectangle): number {
if (shape.kind === "circle") {
return Math.PI _ shape.radius \*\* 2;
} else {
return shape.width _ shape.height;
}
}
 

Theoretical Questions

  1. TypeScript vs JavaScript: Explain the main differences between TypeScript and JavaScript. Why would a developer choose TypeScript over JavaScript?

TypeScript is a superset of JavaScript, adding static typing and additional features like interfaces and generics. Developers choose TypeScript for its type safety, which enhances code quality and maintainability, especially in large-scale applications.

  1. Type Annotations: Describe what type annotations are in TypeScript and how they are used.

Type annotations in TypeScript allow developers to explicitly specify the type of variables, function parameters, and return types, enabling the TypeScript compiler to type-check the code and catch errors during development.

let age: number = 25;
  1. Interface vs Type Alias: Compare and contrast interfaces and type aliases in TypeScript. When should one be used over the other?

Interfaces in TypeScript are used to define the shape of objects and can be extended or implemented by classes. Type aliases can describe more complex types, like unions or intersections. Interfaces are preferred for object shapes, while type aliases are suitable for more complex type definitions.

interface User {
  name: string;
}
 
type Point = { x: number; y: number };
  1. Generics: Explain the concept of generics in TypeScript. Provide an example of a generic function.

Generics in TypeScript enable functions, classes, and interfaces to work with multiple data types without losing type safety. An example of a generic function is one that takes an array of any type and returns its length.

function getLength<T>(array: T[]): number {
  return array.length;
}
  1. Enums: What are Enums in TypeScript and how are they useful?

Enums in TypeScript provide a way to define a set of named constants, either numeric or string-based, making code more readable and maintainable by giving a set of predefined options.

enum Color {
  Red,
  Green,
  Blue,
}
  1. TypeScript's Compilation Process: Describe how TypeScript is compiled into JavaScript. What does the TypeScript compiler do?

TypeScript is compiled into JavaScript using the TypeScript compiler. The compiler checks the code for type-related errors and transpiles TypeScript code into JavaScript, compatible with different browsers or Node.js.

  1. Type Inference: Discuss type inference in TypeScript. How does TypeScript infer the type of a variable?

TypeScript's type inference automatically deduces types of variables and expressions if they are not explicitly specified. This is done based on initial assignments, return statements, and usage in the code.

let age = 25; // inferred as number
  1. Type Guards: What are type guards and how are they implemented in TypeScript?

Type guards in TypeScript are techniques used to narrow down the type of a variable within conditional blocks. This includes using type predicates, typeof, instanceof, and user-defined type guards.

function isNumber(x: any): x is number {
  return typeof x === "number";
}
  1. Decorators: Explain what decorators are in TypeScript and provide an example of their use.

Decorators in TypeScript are special declarations that can be attached to classes, methods, accessors, properties, or parameters. They are used for modifying or annotating the behavior of the element they are attached to.

function sealed(constructor: Function) {
  Object.seal(constructor);
  Object.seal(constructor.prototype);
}
 
@sealed
class Greeter {}
  1. Advanced Types: Explain the purpose of union, intersection, and conditional types in TypeScript. Provide examples of each.

Union types allow a value to be one of several types. Intersection types combine multiple types into one. Conditional types choose types based on conditions. These features offer flexibility in defining complex type relationships.

type UnionType = string | number;
type IntersectionType = { name: string } & { age: number };
type ConditionalType = string extends T ? number : boolean;
  1. Modules and Namespaces: Discuss the difference between modules and namespaces in TypeScript.

Modules in TypeScript are used for organizing and encapsulating code, and are files containing exports and imports. Namespaces, on the other hand