0% found this document useful (0 votes)
5 views18 pages

Lab13 TypeScript

Lab13 introduces students to TypeScript, covering static typing benefits, environment setup, basic types, interfaces, function types, classes, and advanced types like union types and enums. The lab includes hands-on activities to reinforce learning through practical coding exercises. Prerequisites include a solid understanding of JavaScript and tools like Node.js and VS Code.

Uploaded by

minahil ashfaq
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views18 pages

Lab13 TypeScript

Lab13 introduces students to TypeScript, covering static typing benefits, environment setup, basic types, interfaces, function types, classes, and advanced types like union types and enums. The lab includes hands-on activities to reinforce learning through practical coding exercises. Prerequisites include a solid understanding of JavaScript and tools like Node.js and VS Code.

Uploaded by

minahil ashfaq
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 18

Lab13 – Introduction to TypeScript for Web Development

Objective: This lab aims to introduce students to the fundamentals of


TypeScript, a superset of JavaScript that adds static typing. By the end of this lab,
you will be able to:
 Understand the benefits of static typing in JavaScript development.
 Set up a TypeScript development environment.
 Work with basic TypeScript types (primitives, any, arrays).
 Define custom object shapes using interfaces and type aliases.
 Type function parameters, return values, and define optional/default
parameters.
 Implement basic classes with type annotations.
 Utilize advanced types like union types, literal types, and enums.
Prerequisites:
 Solid understanding of JavaScript fundamentals (variables, functions,
objects, arrays, basic loops, conditional statements).
 Node.js and npm (Node Package Manager) installed on your machine.
 A code editor (VS Code is highly recommended for its excellent TypeScript
support).
Estimated Time: 3-4 hours
Setup: Setting Up Your TypeScript Environment
Before we begin with the activities, let's set up your project.
1. Create a new project directory:
mkdir typescript-lab
cd typescript-lab
2. Initialize a new Node.js project:
npm init -y
This creates a package.json file.
3. Install TypeScript globally (optional, but convenient) or locally:
o Globally (allows tsc command anywhere):

npm install -g typescript


o Locally (recommended for project-specific versions):

npm install --save-dev typescript


If installed locally, you'll run npx tsc instead of just tsc.
4. Initialize a TypeScript configuration file:
npx tsc --init
This command creates a tsconfig.json file in your project root. This file configures
how the TypeScript compiler (tsc) behaves.
5. Configure tsconfig.json (minimal changes): Open tsconfig.json. Find
and uncomment/change the following lines:
"rootDir": "./src", (Tells TypeScript where your source files are)
"outDir": "./dist", (Tells TypeScript where to put compiled JavaScript
files)
"esModuleInterop": true, (Helps with module imports/exports
compatibility)
"strict": true, (Enables a broad range of type-checking validation rules -
recommended for learning!)
6. Create your source directory:
mkdir src
Now your project structure should look something like this:
typescript-lab/
├── node_modules/
├── package.json
├── package-lock.json
├── tsconfig.json
└── src/
Compilation and Running:
To compile your TypeScript files into JavaScript:
npx tsc
(This will compile all .ts files in src and output .js files to dist.)
To run your compiled JavaScript files:
node dist/index.js
(Assuming your main compiled file is dist/index.js)
For continuous compilation during development, use watch mode:
npx tsc --watch

Activity 1: Basic Types and Type Inference


Goal: Understand primitive types (string, number, boolean), arrays, any, and
how TypeScript infers types.
Instructions:
1. Create a new file src/activity1.ts.
2. Declare variables with explicit type annotations:
o Declare a string variable named userName and assign your name.

o Declare a number variable named age and assign your age.

o Declare a boolean variable named isStudent and assign true.

o Try to assign a number to userName and observe the TypeScript


error.
3. Declare an array with explicit type annotation:
o Declare an array of strings named hobbies and assign a few
hobbies.
o Try to push a number into hobbies and observe the TypeScript error.

4. Observe Type Inference:


o Declare a variable country and assign a string value without an
explicit type.
o Declare a variable pi and assign 3.14159 without an explicit type.

o Hover over these variables in VS Code to see what type TypeScript


infers for them.
o Try to assign a boolean to country and observe the error.

5. Use the any type:


o Declare a variable flexibleData with the type any.

o Assign a number, then a string, then an object to flexibleData.

o Notice how TypeScript allows any assignment without error when


any is used.
6. Add console.log() statements to print the values of your variables.
7. Compile src/activity1.ts using npx tsc src/activity1.ts and then run the
compiled JavaScript file from the dist folder.
Solution:
// src/activity1.ts

// 1. Explicit Type Annotations


let userName: string = "Alice";
let age: number = 30;
let isStudent: boolean = true;

// --- Observe errors here (uncomment to see) ---


// userName = 123; // Error: Type 'number' is not assignable to type 'string'.
// age = "twenty"; // Error: Type 'string' is not assignable to type 'number'.
// isStudent = "yes"; // Error: Type 'string' is not assignable to type 'boolean'.

console.log(`Explicit Types:`);
console.log(`Name: ${userName}, Type: ${typeof userName}`);
console.log(`Age: ${age}, Type: ${typeof age}`);
console.log(`Is Student: ${isStudent}, Type: ${typeof isStudent}`);
console.log('--------------------');

// 2. Array Type Annotations


let hobbies: string[] = ["reading", "hiking", "coding"];
// let hobbies: Array<string> = ["reading", "hiking", "coding"]; // Alternative
syntax

// --- Observe errors here (uncomment to see) ---


// hobbies.push(123); // Error: Argument of type 'number' is not assignable to
parameter of type 'string'.

console.log(`Hobbies: ${hobbies.join(", ")}`);


console.log('--------------------');

// 3. Type Inference
let country = "Canada"; // TypeScript infers 'string'
let pi = 3.14159; // TypeScript infers 'number'
let isActive = false; // TypeScript infers 'boolean'

// --- Observe errors here (uncomment to see) ---


// country = 123; // Error: Type 'number' is not assignable to type 'string'.
// pi = "not a number"; // Error: Type 'string' is not assignable to type 'number'.

console.log(`Inferred Types:`);
console.log(`Country: ${country}, Type: ${typeof country}`);
console.log(`Pi: ${pi}, Type: ${typeof pi}`);
console.log(`Is Active: ${isActive}, Type: ${typeof isActive}`);
console.log('--------------------');

// 4. The 'any' type


let flexibleData: any = 10;
console.log(`Flexible Data (number): ${flexibleData}, Type: ${typeof
flexibleData}`);

flexibleData = "Hello World";


console.log(`Flexible Data (string): ${flexibleData}, Type: ${typeof
flexibleData}`);

flexibleData = { name: "john", id: 1 };


console.log(`Flexible Data (object):`, flexibleData, `, Type: ${typeof
flexibleData}`);

console.log('--------------------');

// To run this:
// 1. npx tsc src/activity1.ts
// 2. node dist/activity1.js

Activity 2: Interfaces and Custom Types


Goal: Learn to define custom object structures using interfaces and type aliases
to improve code readability and maintainability.
Instructions:
1. Create a new file src/activity2.ts.
2. Define an interface for a Product:
o The interface should specify properties: id (number), name (string),
price (number), and an optional description (string).
o Create two Product objects that adhere to this interface. One should
include the optional description, the other should not.
o Try to create a Product object that is missing a required property or
has an incorrect type, and observe the error.
3. Define a type alias for a simple union of string literals:
o Create a type alias named OrderStatus that can only be one of
"pending", "shipped", "done", or "cancelled".
o Declare a variable currentOrder of type OrderStatus and assign a
valid value.
o Try to assign an invalid string value and observe the error.

4. Define an interface for a function type:


o Create an interface StringFormatter that describes a function that
takes a string and returns a string.
o Implement a function toUppercase that adheres to this
StringFormatter interface and converts a string to uppercase.
o Implement another function addExclamation that also adheres to it.

5. Add console.log() statements to display your product objects and test your
functions.
6. Compile and run src/activity2.ts.
Solution:
// src/activity2.ts

// 1. Interface for a Product


interface Product {
id: number;
name: string;
price: number;
description?: string; // Optional property
}

const product1: Product = {


id: 101,
name: "Laptop Pro",
price: 1200.00,
description: "High-performance laptop for professionals."
};

const product2: Product = {


id: 102,
name: "Wireless Mouse",
price: 25.50
// No description for product2
};

// --- Observe errors here (uncomment to see) ---


// const invalidProduct: Product = {
// id: 103,
// name: "Headphones",
// // price: "fifty" // Error: Type 'string' is not assignable to type 'number'.
// };

console.log("Products:");
console.log(product1);
console.log(product2);
console.log('--------------------');

// 2. Type Alias for String Literals (Union Type)


type OrderStatus = "pending" | "shipped" | "done" | "cancelled";

let currentOrder: OrderStatus = "pending";


console.log(`Current Order Status: ${currentOrder}`);

currentOrder = "shipped";
console.log(`Updated Order Status: ${currentOrder}`);

// --- Observe errors here (uncomment to see) ---


// currentOrder = "processing"; // Error: Type '"processing"' is not assignable to
type 'OrderStatus'.

console.log('--------------------');

// 3. Interface for a Function Type


interface StringFormatter {
(str: string): string;
}

const toUppercase: StringFormatter = (text: string): string => {


return text.toUpperCase();
};

const addExclamation: StringFormatter = (text: string): string => {


return `${text}!`;
};

console.log(`Formatted String (Uppercase): ${toUppercase("hello typescript")}`);


console.log(`Formatted String (Exclamation): ${addExclamation("typescript is
fun")}`);
console.log('--------------------');

// To run this:
// 1. npx tsc src/activity2.ts
// 2. node dist/activity2.js

Activity 3: Functions and Classes


Goal: Learn how to type function parameters and return values, handle
optional/default parameters, and define basic TypeScript classes.
Instructions:
1. Create a new file src/activity3.ts.
2. Type function parameters and return values:
o Create a function addNumbers that takes two number parameters
and returns their number sum.
o Create a function greetUser that takes a string parameter name and
returns a string greeting message.
3. Implement optional and default parameters:
o Modify greetUser to have an optional greeting parameter (string). If
not provided, it should default to "Hello".
o Create a function calculateArea that takes length (number) and
width (number). Make width an optional parameter. If width is not
provided, it should default to the same value as length (making it a
square).
4. Define a simple class:
o Create a class Car with properties: make (string), model (string),
and year (number).
o Define a constructor that initializes these properties.

o Add a method getCarInfo() that returns a string describing the car


(e.g., "Ford Focus (2020)").
o Create an instance of Car and call its getCarInfo() method.

5. Add console.log() statements to test your functions and class methods.


6. Compile and run src/activity3.ts.
Solution:
// src/activity3.ts

// 1. Typed Function Parameters and Return Values


function addNumbers(a: number, b: number): number {
return a + b;
}

function greetUser(name: string): string {


return `Hello, ${name}!`;
}

console.log(`Sum of 5 and 7: ${addNumbers(5, 7)}`);


console.log(`Greeting: ${greetUser("Maria")}`);
console.log('--------------------');

// 2. Optional and Default Parameters


function greetUserWithOptional(name: string, greeting?: string): string {
// If greeting is provided, use it; otherwise, default to "Hello"
return `${greeting || "Hello"}, ${name}!`;
}

function greetUserWithDefault(name: string, greeting: string = "Hi"): string {


return `${greeting}, ${name}!`;
}

function calculateArea(length: number, width?: number): number {


// If width is not provided, assume it's a square
const actualWidth = width === undefined ? length : width;
return length * actualWidth;
}

console.log(`Greeting with optional (no greeting): $


{greetUserWithOptional("John")}`);
console.log(`Greeting with optional (custom greeting): $
{greetUserWithOptional("John", "Good morning")}`);
console.log(`Greeting with default (no greeting): $
{greetUserWithDefault("Sarah")}`);
console.log(`Greeting with default (custom greeting): $
{greetUserWithDefault("Sarah", "Welcome")}`);
console.log(`Area of square (side 5): ${calculateArea(5)}`);
console.log(`Area of rectangle (5x10): ${calculateArea(5, 10)}`);
console.log('--------------------');

// 3. Defining a Simple Class


class Car {
make: string;
model: string;
year: number;

constructor(make: string, model: string, year: number) {


this.make = make;
this.model = model;
this.year = year;
}

getCarInfo(): string {
return `${this.make} ${this.model} (${this.year})`;
}
}

const myCar = new Car("Honda", "Civic", 2022);


const anotherCar = new Car("Tesla", "Model 3", 2023);

console.log(`My Car Info: ${myCar.getCarInfo()}`);


console.log(`Another Car Info: ${anotherCar.getCarInfo()}`);
console.log('--------------------');

// To run this:
// 1. npx tsc src/activity3.ts
// 2. node dist/activity3.js

Activity 4: Union Types, Literals, and Enums


Goal: Explore more advanced typing features like union types, literal types, and
enums for creating more flexible yet type-safe code.
Instructions:
1. Create a new file src/activity4.ts.
2. Union Types:
o Declare a variable id that can be either a string or a number. Assign
a number, then assign a string to it.
o Create a function printId that accepts an id parameter which can be
a string or a number. Inside the function, use type narrowing (e.g.,
typeof id === 'string') to perform different actions based on the
actual type of id.
3. Literal Types:
o Declare a variable direction that can only be one of the literal
strings: "up", "down", "left", or "right".
o Assign a valid literal string to direction.

o Try to assign an invalid string and observe the error.

4. Enums (Numeric and String):


o Define a numeric enum UserRole with values like ADMIN, EDITOR,
VIEWER. Assign default values or explicit numbers.
o Declare a variable currentUserRole of type UserRole and assign
UserRole.EDITOR. Print its numeric value.
o Define a string enum HttpMethod with values like GET, POST, PUT,
DELETE.
o Declare a variable requestMethod of type HttpMethod and assign
HttpMethod.POST. Print its string value.
5. Add console.log() statements to demonstrate each concept.
6. Compile and run src/activity4.ts.
Solution:
// src/activity4.ts

// 1. Union Types
let id: number | string = 123;
console.log(`ID (number): ${id}`);
id = "abc-456";
console.log(`ID (string): ${id}`);

function printId(id: number | string): void {


if (typeof id === 'string') {
console.log(`ID is a string: ${id.toUpperCase()}`);
} else {
console.log(`ID is a number: ${id.toFixed(2)}`);
}
}

printId(100.123);
printId("my_unique_id");
// printId(true); // Error: Argument of type 'boolean' is not assignable to
parameter of type 'string | number'.
console.log('--------------------');

// 2. Literal Types
let direction: "up" | "down" | "left" | "right";
direction = "up";
console.log(`Direction: ${direction}`);

// --- Observe errors here (uncomment to see) ---


// direction = "forward"; // Error: Type '"forward"' is not assignable to type '"up" |
"down" | "left" | "right"'.

console.log('--------------------');

// 3. Enums (Numeric and String)

// Numeric Enum
enum UserRole {
ADMIN, // 0 by default
EDITOR, // 1
VIEWER = 5, // Explicit value, next will be 6
GUEST // 6
}

let currentUserRole: UserRole = UserRole.EDITOR;


console.log(`Current User Role (Numeric Enum): ${currentUserRole}`); // Output:
1
console.log(`Name of Role 5: ${UserRole[5]}`); // Output: VIEWER

// String Enum
enum HttpMethod {
GET = "GET",
POST = "POST",
PUT = "PUT",
DELETE = "DELETE"
}

let requestMethod: HttpMethod = HttpMethod.POST;


console.log(`Request Method (String Enum): ${requestMethod}`); // Output:
POST

// --- Observe errors here (uncomment to see) ---


// let invalidMethod: HttpMethod = "PATCH"; // Error: Type '"PATCH"' is not
assignable to type 'HttpMethod'.

console.log('--------------------');

// To run this:
// 1. npx tsc src/activity4.ts
// 2. node dist/activity4.js

Activity 5: Generics
Goal: Understand how to use generics to create reusable components and
functions that work with a variety of types while maintaining type safety.
Instructions:
1. Create a new file src/activity5.ts.
2. Generic Identity Function:
o Create a generic function identity<T>(arg: T): T that simply returns
the argument it receives.
o Call this function with a number, a string, and an object. Observe
how TypeScript correctly infers the type T for each call.
3. Generic Array Utility Function:
o Create a generic function getFirstElement<T>(arr: T[]): T |
undefined that takes an array of any type T and returns its first
element, or undefined if the array is empty.
o Test this function with an array of numbers, an array of strings, and
an array of objects.
4. Generic Interface:
o Define a generic interface Box<T> with a single property value: T.

o Create two variables, one of type Box<number> and another of


type Box<string>, and assign appropriate values.
o Try to assign a string to the value of Box<number> and observe the
error.
5. Add console.log() statements to demonstrate each concept.
6. Compile and run src/activity5.ts.
Solution:
// src/activity5.ts

// 1. Generic Identity Function


function identity<T>(arg: T): T {
return arg;
}

// Demonstrating type inference with generics


let numValue = identity(123); // T is inferred as number
let stringValue = identity("Hello Generics"); // T is inferred as string
let objValue = identity({ name: "Generic Object", id: 1 }); // T is inferred as
{ name: string; id: number; }

console.log(`Generic Identity (number): ${numValue}, Type: ${typeof


numValue}`);
console.log(`Generic Identity (string): ${stringValue}, Type: ${typeof
stringValue}`);
console.log(`Generic Identity (object):`, objValue, `, Type: ${typeof objValue}`);
console.log('--------------------');

// 2. Generic Array Utility Function


function getFirstElement<T>(arr: T[]): T | undefined {
return arr.length > 0 ? arr[0] : undefined;
}
let numbers = [1, 2, 3];
let firstNum = getFirstElement(numbers); // T is inferred as number
console.log(`First number: ${firstNum}`);

let words = ["apple", "banana", "cherry"];


let firstWord = getFirstElement(words); // T is inferred as string
console.log(`First word: ${firstWord}`);

interface User {
id: number;
name: string;
}
let users: User[] = [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }];
let firstUser = getFirstElement(users); // T is inferred as User
console.log(`First user:`, firstUser);

let emptyArray: string[] = [];


let firstOfEmpty = getFirstElement(emptyArray); // T is inferred as string |
undefined
console.log(`First of empty array: ${firstOfEmpty}`);
console.log('--------------------');

// 3. Generic Interface
interface Box<T> {
value: T;
}

let numberBox: Box<number> = { value: 42 };


console.log(`Number Box Value: ${numberBox.value}`);

let stringBox: Box<string> = { value: "TypeScript in a box!" };


console.log(`String Box Value: ${stringBox.value}`);

// --- Observe errors here (uncomment to see) ---


// numberBox.value = "hello"; // Error: Type 'string' is not assignable to type
'number'.

console.log('--------------------');

// To run this:
// 1. npx tsc src/activity5.ts
// 2. node dist/activity5.js

Activity 6: Type Assertions and Type Guards


Goal: Learn how to use type assertions and type guards for more precise type
checking in situations where TypeScript can't infer the type automatically, or
when you have more specific knowledge about a type.
Instructions:
1. Create a new file src/activity6.ts.
2. Type Assertion (as keyword or <Type> syntax):
o Declare a variable someValue: any = "this is a string";.

o Use type assertion (someValue as string) to treat someValue as a


string and call the length property on it.
o Declare a variable anotherValue: any = 123.456;.

o Use type assertion (<number>anotherValue) to treat anotherValue


as a number and call toFixed(2) on it.
o Caution: Discuss in your notes why type assertions should be used
carefully, as they bypass compile-time checks.
3. Type Guards (typeof, instanceof, in operator):
o typeof Type Guard:

 Create a union type Combinable = string | number;.


 Create a function addOrConcatenate(a: Combinable, b:
Combinable): Combinable that:
 If both a and b are numbers, it returns their sum.
 If both a and b are strings, it returns their
concatenation.
 Otherwise (e.g., one string and one number), log an
error and return null (or throw an error). Use typeof
checks.
o instanceof Type Guard:

 Define two simple classes: Dog (with a bark() method) and


Cat (with a meow() method).
 Create a function makeSound(animal: Dog | Cat): void that
uses instanceof to determine if animal is a Dog or a Cat and
calls the appropriate method.
o in Operator Type Guard:

 Define two interfaces: Car { drive(): void; } and Boat { sail():


void; }.
 Create a function startVehicle(vehicle: Car | Boat): void that
uses the in operator to check for the existence of the drive or
sail property and calls the relevant method.
4. Add console.log() statements to demonstrate each concept.
5. Compile and run src/activity6.ts.
Solution:
// src/activity6.ts
// 1. Type Assertion (`as` keyword or `<Type>` syntax)
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
console.log(`String length (using 'as'): ${strLength}`);

let anotherValue: any = 123.456;


let fixedNumber: string = (<number>anotherValue).toFixed(2);
console.log(`Fixed number (using '<type>'): ${fixedNumber}`);
console.log('--------------------');

// 2. Type Guards

// typeof Type Guard


type Combinable = string | number;

function addOrConcatenate(a: Combinable, b: Combinable): Combinable | null {


if (typeof a === 'number' && typeof b === 'number') {
return a + b;
} else if (typeof a === 'string' && typeof b === 'string') {
return a + b;
} else {
console.error("Error: Cannot add/concatenate mixed types.");
return null;
}
}

console.log(`Add numbers: ${addOrConcatenate(10, 20)}`);


console.log(`Concatenate strings: ${addOrConcatenate("Hello", "World")}`);
addOrConcatenate(10, "World"); // This will log an error
console.log('--------------------');

// instanceof Type Guard


class Dog {
bark(): void {
console.log("Woof!");
}
}

class Cat {
meow(): void {
console.log("Meow!");
}
}

function makeSound(animal: Dog | Cat): void {


if (animal instanceof Dog) {
animal.bark();
} else if (animal instanceof Cat) {
animal.meow();
}
}

const myDog = new Dog();


const myCat = new Cat();
makeSound(myDog);
makeSound(myCat);
console.log('--------------------');

// 'in' Operator Type Guard


interface Car {
drive(): void;
}

interface Boat {
sail(): void;
}

function startVehicle(vehicle: Car | Boat): void {


if ('drive' in vehicle) {
vehicle.drive();
} else if ('sail' in vehicle) {
vehicle.sail();
}
}

const myCarInstance: Car = {


drive: () => console.log("Driving the car...")
};

const myBoatInstance: Boat = {


sail: () => console.log("Sailing the boat...")
};

startVehicle(myCarInstance);
startVehicle(myBoatInstance);
console.log('--------------------');

// To run this:
// 1. npx tsc src/activity6.ts
// 2. node dist/activity6.js

Graded Task: Simple Inventory Management System


Goal: Design and implement a basic inventory management system using all the
TypeScript concepts learned in this lab.
Instructions:
1. Create a new file src/gradedTask.ts.
2. Define an interface for an InventoryItem:
o Properties: id (number), name (string), category (string literal type:
"Electronics", "Books", "Clothing", "Food"), quantity (number), and
price (number).
o The description property (string) should be optional.
3. Define a class called Inventory:
o It should have a private property items which is an array of
InventoryItems.
o Constructor: Initializes the items array.

o Method: addItem(item: InventoryItem): void

 Adds a new item to the items array.


 Ensure the id is unique. If an item with the same ID already
exists, log an error and do not add.
o Method: getItemById(id: number): InventoryItem |
undefined
 Returns an InventoryItem if found, or undefined if not found.
o Method: updateItemQuantity(id: number, newQuantity:
number): boolean
 Updates the quantity of an existing item.
 Returns true if updated, false if item not found or
newQuantity is invalid (e.g., negative).
o Method: removeItem(id: number): boolean

 Removes an item by its ID.


 Returns true if removed, false if item not found.
o Method: listAllItems(): InventoryItem[]

 Returns a copy of the entire items array.


o Method: listItemsByCategory(category: "Electronics" |
"Books" | "Clothing" | "Food"): InventoryItem[]
 Returns an array of items belonging to the specified category.
4. Demonstrate Usage:
o Create an instance of the Inventory class.

o Add at least 5-7 diverse items using addItem. Include items from
different categories and some with descriptions.
o Attempt to add an item with a duplicate ID.

o Use getItemById to retrieve an item and print its details.

o Use updateItemQuantity to change an item's quantity.

o Attempt to update a non-existent item or with an invalid quantity.

o Use removeItem to remove an item.

o Attempt to remove a non-existent item.


o Use listAllItems and listItemsByCategory to print various lists of
items to the console.

You might also like