⇦ Back

WDX-180

Web Development X

TypeScript Exercises

VARIABLES

01 - Variable Type Annotations

STEP:

let phoneNumber;

if (Math.random() > 0.5) {
  phoneNumber = "+61770102062";
} else {
  phoneNumber = 7167762323;
}

Try in TS Playground

FUNCTIONS

02 - Parameter Type Annotations

STEP:

function triple(value) {
  return value * 3;
}

function greetTripled(greeting, value) {
  console.log(`${greeting}, ${triple(value)}!`);
}

greetTripled(5, "Hiya");

Try in TS Playground

03 - Optional Parameters

Our proclaim() method is meant to default to printing ‘I’m not ready…’ when called without arguments. Mark its status parameter as optional.

Afterwards, feel free to run tsc in the terminal to verify that there are no errors.

function proclaim(status: string) {
  console.log(`I'm ${status || "not ready..."}`);
}

proclaim();
proclaim("ready?");
proclaim("ready!");

Try in TS Playground

04 - Default Parameters

STEP:

function proclaim(status?: string, repeat?: number) {
  for (let i = 0; i < repeat || 0; i += 1) {
    console.log(`I'm ${status || "not ready..."}`);
  }
}

proclaim();
proclaim("ready?");
proclaim("ready!", 3);

Try in TS Playground

05 - Inferring Return Types

Challenge! Using what you’ve learned above, create a variable myVar with the type number. To make this more interesting:

function getRandomNumber() {
  return Math.random();
}

Try in TS Playground

06 - Void Return Type

function makeFruitSalad(fruit1: string, fruit2: string): string {
  let salad = fruit1 + fruit2 + fruit2 + fruit1 + fruit2 + fruit1 + fruit1;
  console.log(salad);
}

makeFruitSalad("banana", "pineapple");

Try in TS Playground

07 - Documenting Functions

We grabbed a few functions from earlier exercises. They are sorely missing some documentation comments…

Add a documentation comment makeFruitSalad() function. Your comment should include:

Add a documentation comment proclaim() function. Your comment should include:

function makeFruitSalad(fruit1: string, fruit2: string): void {
  let salad = fruit1 + fruit2 + fruit2 + fruit1 + fruit2 + fruit1 + fruit1;
  console.log(salad);
}

function proclaim(status = "not ready...", repeat = 1) {
  for (let i = 0; i < repeat; i += 1) {
    console.log(`I'm ${status}`);
  }
}

Try in TS Playground

ARRAYS

08 - Array Type Annotations

The code editor contains several array assignments. Add the appropriate type annotations to the array variables in the // Arrays: section.

// Arrays:
let bestNumbers = [7, 77, 4];
let bestLunches = ["chicken soup", "non-chicken soup"];
let bestBreakfasts = [
  "scrambled eggs",
  "oatmeal",
  "tamago kake gohan",
  "any kind of soup",
];
let bestBooleans = [true, false];

Try in TS Playground

09 - Multi-dimensional Arrays

Please provide type annotations for all the arrays provided in the // Multidimensional arrays: section.

// Arrays:
let bestNumbers: number[] = [7, 77, 4];
let bestLunches: string[] = ["chicken soup", "non-chicken soup"];
let bestBreakfasts: string[] = [
  "fasting",
  "oatmeal",
  "tamago kake gohan",
  "any kind of soup",
];
let bestBooleans: boolean[] = [true, false];

// // Multidimensional Arrays:
let bestMealPlan = [
  bestLunches,
  bestBreakfasts,
  ["baked potato", "mashed potato"],
];
let bestBooleansTwice = [bestBooleans, bestBooleans];
let numbersMulti = [
  [[1], [2, 3]],
  [[7], bestNumbers],
];

Try in TS Playground

10 - Tuples

STEP:

let favoriteCoordinates = [40, 43.2, "N", 73, 59.8, "W"];

Try in TS Playground

11 - Array Type Inference

STEP:

// Don't change this part:
let dogTup: [string, string, string, string] = [
  "dog",
  "brown fur",
  "curly tail",
  "sad eyes",
];

// Your code goes here:

Try in TS Playground

12 - Rest Parameters

STEP:

function addPower(p, ...numsToAdd) {
  let answer = 0;
  for (let i = 0; i < numsToAdd.length; i++) {
    answer += numsToAdd[i] ** p;
  }
  return answer;
}

Try in TS Playground

13 - Spread Syntax

STEP:

function performDanceMove(
  moveName: string,
  moveReps: number,
  hasFlair: boolean
): void {
  console.log(`I do the ${moveName} ${moveReps} times !`);
  if (hasFlair) {
    console.log("I do it with flair!");
  }
}

let danceMoves = [
  ["chicken beak", 4, false],
  ["wing flap", 4, false],
  ["tail feather shake", 4, false],
  ["clap", 4, false],
  ["chicken beak", 4, true],
  ["wing flap", 4, true],
  ["tail feather shake", 4, true],
  ["clap", 4, true],
];

Try in TS Playground

CUSTOM TYPES

14 - Enums

STEP:

let petOnSale = "chinchilla";
let ordersArray = [
  ["rat", 2],
  ["chinchilla", 1],
  ["hamster", 2],
  ["chinchilla", 50],
];

// Write your code below:

Try in TS Playground

15 - String Enums vs. Numeric Enums

STEP:

let petOnSale = "chinchilla";
let ordersArray = [
  ["rat", 2],
  ["chinchilla", 1],
  ["hamster", 2],
  ["chinchilla", 50],
];

// Write your code below:

Try in TS Playground

16 - Object Types

STEP:

function sayHappyBirthdayWithObject(personObject){
  let output ='';
  output += 'Happy Birthday '
         + personObject.name + '! ';
  output += 'You are now ' 
         + personObject.age + ' years old! ';
  output += 'Your birthday wish was to receive ' 
         + personObject.giftWish 
         + '. And guess what? You will ';
  if (!personObject.success){
    output += 'not ';
  }
  output += 'receive it! \n';
  console.log(output);
}

let birthdayBabies = [
  {name: 'Liam', age: 0, giftWish: 'karate skills', success: false}, 
  {name: 'Olivia', age: 0, giftWish: 'a bright future', success:true}, 
  {name: 'Ava', age: 0, giftWish: '$0.25', success:true}
]; 

birthdayBabies.forEach(sayHappyBirthdayWithObject);

Try in TS Playground

17 - Type Aliases

STEP:

// Add your type alias below:

let codecademyCoordinates = [40, 43.2, "N", 73, 59.8, "W"];
let bermudaTCoordinates = [25, 0, "N", 71, 0, "W"];

Try in TS Playground

18 - Function Types

STEP:

// Math Operations
function add(a, b) {
  return a + b;
}
function subtract(a, b) {
  return a - b;
}
function multiply(a, b) {
  return a * b;
}
function divide(a, b) {
  return a / b;
}
function wrongAdd(a, b) {
  return a + b + "";
}

// Add your function type below:

// Math Tutor Function That Accepts a Callback
function mathTutor(operationCallback) {
  console.log("Let's learn how to", operationCallback.name, "!");
  let value25 = operationCallback(2, 5);
  console.log(
    "When we",
    operationCallback.name,
    "2 and 5, we get",
    value25,
    "."
  );
  console.log(
    "When we",
    operationCallback.name,
    value25,
    "and 7, we get",
    operationCallback(value25, 7),
    "."
  );
  console.log("Now fill out this worksheet.");
}

// Call your functions below:

Try in TS Playground

19 - Generic Types

Please provide type annotations for the variables theFamily, someFamily, aFamily, and anotherFamily in the code editor. Where appropriate, use the predefined type aliases Human, Dog, and the generic type Family<T>.

type Human = { name: string; job: string };
type Dog = { name: string; tailWagSpeed: number };

// Do not change the code above this line.
// Provide type annotations for the variables below:

const theFamily = {
    parents: [3, 4],
    mate: 9,
    children: [5, 30, 121]
};
const someFamily = {
    parents: [true, true],
    mate: false,
    children: [false, false, true, true]
};
const aFamily = {
    parents: [
        { name: "Mom", job: "software engineer" },
        { name: "Dad", job: "coding engineer" },
    ],
    mate: { name: "Matesky", job: "engineering coder" },
    children: [{ name: "Babesky", job: "none" }]
};
const anotherFamily = {
    parents: [
        { name: "Momo", tailWagSpeed: 3 },
        { name: "Dado", tailWagSpeed: 100 },
    ],
    mate: { name: "Cheems", tailWagSpeed: 7 },
    children: [
        { name: "Puppin", tailWagSpeed: 0.001 },
        { name: "Puppenaut", tailWagSpeed: 0.0001 },
        { name: "Puppenator", tailWagSpeed: 0.01 },
    ]
};

Try in TS Playground

20 - Generic Functions

Use the function getFilledArray() to assign values to the variables stringArray, numberArray, personArray, and coordinateArray.

Write your code so that:

Don’t forget to specify the value of T!

function getFilledArray<T>(value: T, n: number): T[] {
  return Array(n).fill(value);
}

let stringArray: string[];
let numberArray: number[];
let personArray: { name: string; age: number }[];
let coordinateArray: [number, number][];

// Write your code below:

Try in TS Playground

UNION TYPES

21 - Defining Unions

STEP

function printNumsAndStrings(statement) {
  console.log(`ℹ️ LOG:: ${statement}`);
}

printNumsAndStrings("hello!");

Try in TS Playground

22 - Type Narrowing

STEP

function formatValue(value: string | number) {
// Write your code here
}

formatValue("Hiya");
formatValue(42);

Try in TS Playground

23 - Inferred Union Return Types

In the editor, we have a User type that describes a user. In addition, there’s a function named createUser() that randomly returns a user or an error message (we’re simulating a call to a server that might fail). We’d like to call the createUser() function, then store its response in a typed variable.

Declare a variable named userData that stores the returned value of createUser(). Then, go back and provide userData with the correct union type.

type User = {
  id: number;
  username: string;
};

function createUser() {
  const randomChance = Math.random() >= 0.5;

  if (randomChance) {
    return { id: 1, username: "nikko" };
  } else {
    return "Could not create a user.";
  }
}

Try in TS Playground

24 - Unions and Arrays

Inspect the program in the editor. This program has a function that takes home addresses and their respective prices, formats them, then returns them. If you hover over the listings parameter in formatListings(), the type of listings is inferred as any. Let’s type this parameter.

Look at the definition of formatListings(), then define a union array type on the listings parameter.

function formatListings(listings) {
  return listings.map((listing) => {
    if (typeof listing === "string") {
      return listing.toUpperCase();
    }

    if (typeof listing === "number") {
      return `$${listing.toLocaleString()}`;
    }
  });
}

const result = formatListings([
  "123 Main St",
  226800,
  "580 Broadway Apt 4a",
  337900,
]);

console.log(result);

Try in TS Playground

25 - Common Key Value Pairs

In the editor, we’ve written a program that should display a message about a social media event. The getFriendNameFromEvent() function takes an event, then returns the friend’s displayName or username. Let’s start by adding a type to the getFriendNameFromEvent()’s event parameter. Use a union to allow event to be a Like or a Share, then save your code.

In getFriendNameFromEvent()‘s body, it returns event.displayName   event.username. Hover over event.displayName. You’ll see a pop-up with this error message:

Property ‘displayName’ does not exist on type ‘Like | Share’. Property ‘displayName’ does not exist on type ‘Share’.(2339)

This message is pointing out that there’s no displayName property on the Share type. In the Share type, add a displayName of type string, just like on the Like type.

type Like = {
  username: string;
  displayName: string;
};

type Share = {
  username: string;
};

function getFriendNameFromEvent(event) {
  return event.displayName || event.username;
}

const newEvent = {
  username: "vkrauss",
  displayName: "Veronica Krauss",
};

const friendName = getFriendNameFromEvent(newEvent);

console.log(`You have an update from ${friendName}.`);

Try in TS Playground

26 - Unions with Literal Types

STEP:

function downloadStatus(status) {
  if (status === "idle") {
    console.log("Download");
  }
  if (status === "downloading") {
    console.log("Downloading...");
  }
  if (status === "complete") {
    console.log("Your download is complete!");
  }
}

downloadStatus("idle");

Try in TS Playground

TYPE NARROWING

27 - Type guards

STEP:

function formatStatistic(stat: string | number) {
  // Write your code below:
  return stat.toFixed(2);
}

console.log(formatStatistic("Win"));
console.log(formatStatistic(0.364));

Try in TS Playground

28 - Using in with Type Guards

STEP:

type Cat = {
  name: string;
  run: () => string;
};

type Fish = {
  name: string;
  swim: () => string;
};

const siameseCat = {
  name: "Proxie",
  run: () => "pitter pat",
};

const bettaFish = {
  name: "Neptune",
  swim: () => "bubble blub",
};

function move(pet: Cat | Fish) {
  return pet.run();
}

console.log(move(siameseCat));

Try in TS Playground

29 - Narrowing with else

STEP:

type Pasta = {
  menuName: string;
  boil: () => string;
};

type Meat = {
  menuName: string;
  panFry: () => string;
};

const fettuccine = {
  menuName: "Fettuccine",
  boil: () => "Heat water to 212 degrees",
};

const steak = {
  menuName: "New York Strip Steak",
  panFry: () => "Heat oil to 350 degrees",
};

function prepareEntree(entree: Pasta | Meat) {
  return entree.boil();
}

console.log(prepareEntree(fettuccine));

Try in TS Playground

30 - Narrowing After a Type Guard

In the editor, we’ve created a program that recycles variables of type Metal and Glass. The goal of the program is to sort out the trash of type Metal before the trash of type Glass.

Right now, the recycle() function calls the .melt() method on each piece of trash. Let’s give the recycle() function the ability to sort out pieces of trash of type Metal.

In the body of the recycle() function, write a type guard that checks if there is a .magnetize() method on the trash parameter. If there is, then return trash.magnetize(). Your type guard should appear above the trash.melt() call.

type Metal = {
  magnetize: () => string;
};

type Glass = {
  melt: () => string;
};

const iron = {
  magnetize: () => "Electromagnet activated",
};

const bottle = {
  melt: () => "Furnace set to 2,700 degrees",
};

function recycle(trash: Metal | Glass) {
  // Add your code below:

  return trash.melt();
}

console.log(recycle(iron));

Try in TS Playground

ADVANCED OBJECT TYPES

31 - Interfaces and Types

STEP:

// Write an interface here

function updateRunGoal(run) {
  console.log(`
Miles left:       ${50 - run.miles}
Percent of goal:  ${(run.miles / 50) * 100}% complete
  `);
}

updateRunGoal({
  miles: 5,
});

Try in TS Playground

32 - Interfaces and Classes

STEP:

// Write an interface here

class DesktopDirectory {
  addFile(name: string) {
    console.log(`Adding file: ${name}`);
  }

  showPreview(name: string) {
    console.log(`Opening preview of file: ${name}`);
  }
}

const Desktop = new DesktopDirectory();

Desktop.addFile("lesson-notes.txt");
Desktop.showPreview("lesson-notes.txt");

Try in TS Playground

33 - Deep Types

STEP:

interface Directory {
  addFile: (name: string) => void;
  // Define a config type member here
}

class DesktopDirectory implements Directory {

  addFile(name: string) {
    console.log(`Adding file: ${name}`);
  }

  showPreview(name: string) {
    console.log(`Opening preview of file: ${name}`);
  }
}

const Desktop = new DesktopDirectory();

console.log(Desktop.config);

Try in TS Playground

34 - Deep Types

STEP:

interface Directory {
  addFile: (name: string) => void;
  config: {
    default: {
      encoding: string;
      permissions: string;
    };
  };
}

class DesktopDirectory implements Directory {
  config = {
    default: {
      encoding: "utf-8",
      permissions: "drw-rw-rw-",
    },
  };

  addFile(name: string) {
    console.log(`Adding file: ${name}`);
  }

  showPreview(name: string) {
    console.log(`Opening preview of file: ${name}`);
  }
}

const Desktop = new DesktopDirectory();

console.log(Desktop.config);

Try in TS Playground

35 - Extending Interfaces

STEP:

// Write your interface here:

interface Developer {
  code: () => void;
}

const me: Developer = {
  code: () => console.log("Headphones on. Coffee brewed. Editor open."),
  name: "Corrina",
  hobbies: ["Building rockets"],
};

me.code();

Try in TS Playground

36 - Index Signatures

In the code editor, there’s a program that calls a budget API to get your current month’s budget by category. Your goal is to give the result variable the appropriate type inside the getBudget() function.

The call to getBudgetAsync() will return data that looks similar to this:

{
  'shopping': 150,
  'food': 210,
  'utilities': 100
}

The data from getBudgetAsync() could return different names for each category.

Declare an interface named Budget. Use an index signature to make all of its type members have property names of a variable category typed as a string with each key’s value typed as a number.

Apply the Budget interface to the result variable inside the getBudget() function.

In the terminal run tsc to compile your code.

Now run node index.js in the terminal. You should see this month’s budget as the output.

import { getBudgetAsync } from "./api";

// Write an interface here
async function getBudget() {
  const result = await getBudgetAsync();
  console.log(result);
}

getBudget();

Try in TS Playground

37 - Optional Type Members

When creating an app or website, it’s typical that some users might have a first name and last name set, while other users might only have a username. In the code editor, there’s a getUserName() function that checks if a user has both a first and last name. If they do, it returns their full name. If not, it will return their user’s username.

Currently the options parameter on getUserName() is of type any. Let’s give it a type.

Declare an interface at the top of the file named UserNameOptions. It should have three type members:

Apply the UserNameOptions type you created in the last step to the getUserName() function’s options parameter.

In the terminal run tsc to compile your code.

Run node index.js. You should see two formatted names appear.

// Write an interface here

function getUserName(options) {
  if (options.firstName && options.lastName) {
    return console.log(`${options.firstName} ${options.lastName}`);
  }

  return console.log(options.username);
}

getUserName({
  firstName: "Mr.",
  lastName: "Oshiro",
  username: "hotelowner304",
});

getUserName({
  firstName: "Madeline",
  username: "mountainClimber",
});

Try in TS Playground

38 - Generic Functions

Create a function that returns arrays filled with a certain value using TypeScript and its generic functions. Set up a tsconfig that supports ES6 and allows TypeScript code to be compiled by running only the “tsc” command without specifying a filename.

function getFilledArray(value, n) {
  return Array(n).fill(value);
}
console.log(getFilledArray("cheese", 3));

Try in TS Playground

Sources and Attributions


Project maintained by in-tech-gration Hosted on GitHub Pages — Theme by mattgraham