Task 2: Interfaces in TypeScript

Step 1: Create Interfaces

We’ll create interfaces to model the data in our quiz app.

  1. In your src directory, create a new file, models.ts.

  2. In models.ts, define an interface, Question, to represent a quiz question. It should have a string property text for the question text and an array property options to hold the possible answers (strings).

    export interface Question {
      text: string;
      options: string[];
    }
    
  3. Define another interface, Quiz, which should have a string property title for the quiz title and an array property questions to hold an array of Question objects.

    export interface Quiz {
      title: string;
      questions: Question[];
    }
    

Interfaces in TypeScript are a powerful way to define contracts for your code. They are a bit like interfaces in Java but are used more extensively due to TypeScript's structural type system. In Java, an interface defines a contract for classes to adhere to, whereas in TypeScript, an interface is more about defining the shape of data.

Here’s a quick comparison:

  • Java Interface: Defines a contract that classes must implement. Primarily used for defining behavior.
  • TypeScript Interface: Defines the shape of an object. Primarily used for defining and enforcing object structures (data).

Step 2: Define More Data Structures

Let’s add more detail to our data structures. Our app will need to handle user responses, and it would be good to model different types of questions (e.g., multiple-choice, true/false).

  1. Update the Question interface to include an id field of type number and remove the options property.

    export interface Question {
      id: number;
      text: string;
    }
    

    When we created the Question interface, we assumed that each question has a text and some options as answers, similar to multiple-choice questions (MCQs) which are the typical type for quiz questions. However, we are now considering making it more general, and extending it to support different question types.

  2. Extend Question to create MultipleChoiceQuestion and TrueFalseQuestion interfaces to accommodate specific properties of each question type.

    export interface MultipleChoiceQuestion extends Question {
      options: string[]; // list of possible answers
      answer: string; // the correct answer from the options
    }
    
    export interface TrueFalseQuestion extends Question {
      answer: boolean; // whether the statement is true or false
    }
    
  3. Create a new interface, UserResponse, with an id field correlating to a question and an answer field for the user's answer.

    export interface UserResponse {
      questionId: number; // id of the question this response corresponds to
      answer: string | boolean; // user's selected answer, which can be a string (MCQ) or boolean (True/False)
    }
    

    Notice the string | boolean type declaration. The | symbol is used to define a Union Type in TypeScript. A union type is a powerful way to declare a variable that could be more than one type, allowing you to model variability in your structures effectively.

  4. Define a union type, QuizQuestion, which can be either a MultipleChoiceQuestion or a TrueFalseQuestion.

    export type QuizQuestion = MultipleChoiceQuestion | TrueFalseQuestion;
    

    In TypeScript, type and interface are used to define object types. While they can be used interchangeably in many cases, there are some differences between them. type allows you to define union types, intersection types, and mapped types, while interface is more focused on defining the shape of an object. Additionally, type is more flexible and can be used to define more complex types, whereas interface is generally simpler and easier to read.

  5. Finally, update the Quiz interface:

    // To store quiz details along with questions
    export interface Quiz {
      title: string;
      questions: QuizQuestion[]; // the list can include both MCQs and True/False questions
    }
    

Step 3: Quick Overview of Classes in TypeScript

Classes in TypeScript, similar to Java or C++, serve as blueprints for creating objects. They include properties (fields), constructors, and methods, just like classes in other object-oriented programming languages. TypeScript also supports public, private, and protected modifiers, making its classes more similar to Java or C++ than JavaScript's classes. These concepts will be covered in the readings associated with this tutorial lesson.