0% found this document useful (0 votes)
2 views

Lecture #14. VueJS Web app testing (1)

The document discusses various aspects of web app testing using VueJS, including manual and automated testing, types of tests such as unit, integration, functional, and end-to-end tests, and the importance of a structured testing approach. It emphasizes the Testing Pyramid for optimal test distribution and outlines best practices for unit testing, including the use of tools like Jest and Vitest. Additionally, it covers Cypress for end-to-end testing, detailing its features and common commands for effective test execution.

Uploaded by

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

Lecture #14. VueJS Web app testing (1)

The document discusses various aspects of web app testing using VueJS, including manual and automated testing, types of tests such as unit, integration, functional, and end-to-end tests, and the importance of a structured testing approach. It emphasizes the Testing Pyramid for optimal test distribution and outlines best practices for unit testing, including the use of tools like Jest and Vitest. Additionally, it covers Cypress for end-to-end testing, detailing its features and common commands for effective test execution.

Uploaded by

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

Web design

Lecture #14. VueJS Web app testing


The organization issues

Use this link to confirm your attendance in the lecture

Лабораторна робота №1

Лабораторна робота №2

Лабораторна робота №3

2
Manual vs. automated testing

Manual testing is done in person, by clicking through the application or


interacting with the software and APIs with the appropriate tooling.
This is very expensive as it requires someone to set up an environment and
execute the tests themselves, and it can be prone to human error as the tester
might make typos or omit steps in the test script.
Automated tests, on the other hand, are performed by a machine that executes
a test script that has been written in advance.
It's much more robust and reliable than automated tests – but the quality of
your automated tests depends on how well your test scripts have been written.
The different types of tests
Unit tests
Unit tests are very low level, close to the source of your application. They
consist in testing individual methods and functions of the classes, components or
modules used by your software. Unit tests are in general quite cheap to
automate and can be run very quickly by a continuous integration server.
Purpose: testing individual (isolated) functions, classes, components on
programming language level.
Tools: Vitest, Codeception, PHPUnit, Jest, Mocha, etc.
Integration tests
Integration tests verify that different modules or services used by your application work well
together. For example, it can be testing the interaction with the database or making sure that
microservices work together as expected. These types of tests are more expensive to run as
they require multiple parts of the application to be up and running.
Purpose: testing processes or components to behave as expected, including the side effects.
Tools: Codeception, Jest, Mocha, etc.
In unit tests, we mock all dependencies and external functions to test isolated pieces of code.
In integration tests, conversely, we keep most of the dependencies in place and test how
well individual units play with each other.
Functional tests

Functional tests focus on the business requirements of an application. They


only verify the output of an action and do not check the intermediate
states of the system when performing that action.

There is sometimes a confusion between integration tests and functional


tests as they both require multiple components to interact with each other. The
difference is that an integration test may simply verify that you can query
the database while a functional test would expect to get a specific value
from the database as defined by the product requirements.
End-to-end tests
End-to-end testing replicates a user behavior with the software in a complete
application environment. It verifies that various user flows work as expected
and can be as simple as loading a web page or logging in or much more complex
scenarios verifying email notifications, online payments, etc.
End-to-end tests are very useful, but they're expensive to perform and can be
hard to maintain when they're automated. It is recommended to have a few key
end-to-end tests and rely more on lower level types of testing (unit and
integration tests) to be able to quickly identify breaking changes.
Purpose: testing the entire system on browser level; behaving like a real user.
Tools: Codeception, TestCafe, Cypress, Selenium etc.
While unit and integration tests focus on testing code, end-to-end tests
(sometimes called E2E, Acceptance or Functional tests) focus on testing site
features.
The Testing Pyramid (Optimal
Test Distribution)
The Testing Pyramid helps balance test

coverage and efficiency:

1. Unit Tests (70-80%) → Fast,


isolated checks (e.g., add(2, 3) ===
5).

2. Integration Tests (15-20%) →


Tests module interactions (e.g., API
calls).

3. E2E Tests (5-10%) → Full user


workflows (e.g., login → checkout).
Acceptance testing

Acceptance tests are formal tests executed to verify if a system satisfies its
business requirements. They require the entire application to be up and
running and focus on replicating user behaviors. But they can also go further
and measure the performance of the system and reject changes if certain goals
are not met.
Differences between Acceptance
and E2E Testing
1. Purpose / Goal
Acceptance Tests check if the system satisfies business or customer requirements.
E2E Tests check if all parts of the system work together technically.

2. Perspective
Acceptance Testing is from the business or user perspective (e.g., "Can a user buy a product?").
E2E Testing is from the technical user flow perspective (e.g., "Does the 'Buy' button work end-
to-end?")

3. Ownership
Acceptance Tests are often defined by Product Owners, Business Analysts, or QA, possibly
involving non-technical stakeholders.
E2E Tests are usually written by developers or QA engineers using automated tools.

4. Automation: Acceptance tests may be manual or automated. E2E tests are mostly
automated.
10
5. Timing: Acceptance often happens near release ("final check before delivery"). E2E tests run
UI/UX tests
UI UX

● Type and font size


● navigation through the website (or

application) must be easy;


● Colors

● the user must have access to


● Icon styles
information about the product;

● Visual inconsistencies
● the order placement process must be

● Required fields effortless;


Software development and
Testing
Performance testing

Performance tests check the behaviors of the system when it is under


significant load. These tests are non-functional and can have the various form
to understand the reliability, stability, and availability of the platform. For
instance, it can be observing response times when executing a high number of
requests, or seeing how the system behaves with a significant of data.
Performance tests are by their nature quite costly to implement and run, but
they can help you understand if new changes are going to degrade your
system.
Smoke testing

Smoke tests are basic tests that check basic functionality of the application.
They are meant to be quick to execute, and their goal is to give you the assurance
that the major features of the system are working as expected.

Smoke tests can be useful right after a new build is made to decide whether or
not you can run more expensive tests, or right after a deployment to make
sure that they application is running properly in the newly deployed
environment.
Planning, Design, and
Development

During this phase, you create an Automation strategy & plan, which contains the
following details-

● Automation tools selected


● Framework design and its features
● In-Scope and Out-of-scope items of automation
● Automation test preparation
● Schedule and Timeline of scripting and execution
● Deliverables of Automation Testing
Unit Testing

UNIT TESTING is a type of software testing where individual units or


components of a software are tested.
The purpose is to validate that each unit of the software code performs as
expected.
Unit Testing is done during the development (coding phase) of an application
by the developers. Unit Tests isolate a section of code and verify its
correctness. A unit may be an individual function, method, procedure, module, or
object.
Reasons to perform unit testing
Reasons to perform unit testing

Unit tests help to fix bugs early in the development cycle and save costs.
It helps the developers to understand the testing code base and enables
them to make changes quickly
Good unit tests serve as project documentation
Unit tests help with code re-use. Migrate both your code and your tests to your
new project. Tweak the code until the tests run again.
Unit Testing Best Practices

Unit Test cases should be independent. In case of any enhancements or change in


requirements, unit test cases should not be affected.
Test only one code at a time.
Follow clear and consistent naming conventions for your unit tests
In case of a change in code in any module, ensure there is a corresponding
unit Test Case for the module, and the module passes the tests before changing
the implementation
Bugs identified during unit testing must be fixed before proceeding to the next
phase in SDLC
Adopt a "test as your code" approach. The more code you write without
testing, the more paths you have to check for errors.
Vue unit testing with Jest

Jest is a JavaScript unit testing framework created by Facebook which


includes a lot of features like snapshot testing, code coverage, etc.
Vue-test-utils
The vue-test-utils library provides us helper methods by using that we can
mount and interact with the Vue components easily.
Setup

Open the terminal and run the following command.


npm create vue@latest
It will prompt with two options, select manually select features and hit enter.
✔ Project name: … <your-project-name>
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
….
App.vue
Remove everything from a App.vue file and add the below code:
<template>
<div id="app">
<h1>{{msg}}</h1>
</div>
</template>

<script>
export default {
data: function() {
return {
msg: "Hello"
};
}
};
</script>
First unit test
- create a new folder called tests/unit in your root directory
- create a new file called App.test.spec.js
App.test.js
import App from '../src/App.vue'
import { mount } from '@vue/test-utils';
describe('Testing App component', () => {
it('checks textcontent to Hello ', () => {
const wrapper = mount(App); //returns instance of the component.
//accessing dom element and checks textcontent
expect(wrapper.element.textContent).toBe('Hello');
})
})
Vitest
VitestSince the official setup created by create-vue is based on Vite,
we recommend using a unit testing framework that can leverage
the same configuration and transform pipeline directly from Vite.

Vitest is a unit testing framework designed specifically for this


purpose, created and maintained by Vue / Vite team members. It
integrates with Vite-based projects with minimal effort, and is
blazing fast.
Component Testing
In Vue applications, components are the main building blocks of the UI.
Components are therefore the natural unit of isolation when it comes to validating
your application's behavior. From a granularity perspective, component testing sits
somewhere above unit testing and can be considered a form of integration testing.
Much of your Vue Application should be covered by a component test and we
recommend that each Vue component has its own spec file.
Component tests should catch issues relating to your component's props, events,
slots that it provides, styles, classes, lifecycle hooks, and more.
For Visual logic: assert correct render output based on inputted props and slots.

For Behavioral logic: assert correct render updates or emitted events in response to
user input events.
Using vitest and vue-test-utils
together
// Import Vitest tools
import { describe, it, expect } from 'vitest';
// Import Vue Test Utils
import { mount } from '@vue/test-utils';
// Import your component
import MyButton from '@/components/MyButton.vue';

describe('MyButton.vue', () => {
it('renders the correct text when clicked', async () => {
const wrapper = mount(MyButton);
await wrapper.trigger('click');
expect(wrapper.text()).toContain('Clicked');
});
});

26
Cypress: End to End Testing

End to End Testing, or UI testing is one the many approaches for testing a web
application.
An end to end test checks whether a web application works as expected or
not, by testing the so called user flow.
Is End to End Testing important? Yes it is. But, nobody likes E2E tests. They can
be slow, cumbersome and expensive to write.
Testing Your First Application (the course from the authors)
Example
Features

Time Travel: Cypress takes snapshots as your tests run. Hover over commands in the Command
Log to see exactly what happened at each step.
Debuggability: Stop guessing why your tests are failing. Debug directly from familiar tools like
Developer Tools. Our readable errors and stack traces make debugging lightning fast.
Automatic Waiting: Never add waits or sleeps to your tests. Cypress automatically waits for
commands and assertions before moving on. No more async hell.
Spies, Stubs, and Clocks: Verify and control the behavior of functions, server responses, or timers.
The same functionality you love from unit testing is right at your fingertips.
Network Traffic Control: Easily control, stub, and test edge cases without involving your server.
You can stub network traffic however you like.
Consistent Results: Our architecture doesn’t use Selenium or WebDriver. Say hello to fast,
consistent and reliable tests that are flake-free.
Screenshots and Videos: View screenshots taken automatically on failure, or videos of your entire
test suite when run from the CLI.
Cross browser Testing: Run tests within Firefox and Chrome-family browsers (including Edge and
Electron) locally and optimally in a Continuous Integration pipeline.
Running simple E2E Test
Default Test.js:
// https://docs.cypress.io/api/introduction/api.html

describe('My First Test', () => {


it('Visits the app root url', () => {
cy.visit('/')
cy.contains('h1', 'Hello')
})
})
npm run test:e2e
Commonly used commands
cy.get() : Gets the CSS of the element
cy.wait() : Time should be passed in milliseconds. Halts the process for the particular period of time
cy.pause() : Pause the execution of the test only if we manually click the pause button the execution
of the test resumes.
cy.click() : Performs single click action
cy.dblclick() : Performs double click action
cy.rightclick() :Performs right click action
cy.log() : Prints the log in the test runner
cy.reload() : Refreshes the Webpage
cy.clear() : Clears the space before typing in the field
cy.type() : To type in the Webpage element
cy.clearCookies() : Clears cookies of the webpage
cy.clearLocalStorage() : Clears the Local storage of the web page
cy.url() : Mostly used to check the URL while navigating. Gets the current URL
cy.contains() : Checks whether the element contains a specific word.
cy.go("back") OR: cy.go(-1) : To go to the previous Page
cy.go("forward") OR cy.go(1) : To go to the next page
cy.get('CSS').check() : To click the check box
.prev() : Gets the previous element CSS
Handling visible and invisible
elements
cy.get('#displayed-text').should('be.visible')

cy.get('#hide-textbox').click()

cy.get('#displayed-text').should('not.be.visible')

cy.get('#show-textbox').click()

cy.get('#displayed-text').should('be.visible')
Window/Browser Interaction
// Simulate Back and Forward in browser
cy.go(‘back’)
cy.go(‘forward’)
// Navigate to URL
cy.visit(‘https://www.google.co.uk’)
// Refresh the page
cy.reload()
// Scroll the window
//x and y coordinates to scroll to
cy.scrollTo(x, y)
// Clear cookies
cy.clearCookies()
// Take a screenshot, full page or of an element
cy.screenshot()
Interacting with the DOM
// Click an element
cy.get(‘button’).contains(‘Login’).click()
cy.get(‘button’).contains(‘Login’).dblclick()
cy.get(‘button’).contains(‘Login’).rightclick()
// Select an option from a dropdown
cy.get(‘dropdownselector’).select('user-1')
// Trigger an event
cy.get('alink').trigger('mousedown')
Interacting with the DOM
Continued
// Enter or clear text in an input or text field
cy.get(‘textfield’).type(‘stringtotype’)
cy.get(‘textfield’).clear()
// Interact with a checkbox
cy.get(‘checkboxToUse’).check()
cy.get(‘checkboxToUse’).uncheck()
// Focus on an element in the DOM
cy.get(‘textfield’).focus()
// Blur a focused element
cy.get(‘textfield’).blur()
// Force an action even if element may not be actionable
cy.get('button').click({ force: true })
Then

// Use the subject yielded from the previous action


cy.get('.nav').then(($nav) => {})
cy.get(‘button’).then((element) => {
assert.include(element.text().toLowerCase(), ‘login’)
})
cy.wrap(1).then((num) => {
cy.wrap(num).should('equal', 1)
}).should('equal', 1)
cy.get('.brand').then(function(logoElement){
cy.log(logoElement.text())
)}
Assertions using Should
// Check the state
cy.get('checkboxelement’).should('be.checked')
// Check if exists
cy.get('#loading').should('not.exist')
// Check if visible
cy.get('button').should('be.visible')
// Check if enabled
cy.get('checkbox').should('be.enabled)
// Check value
cy.get('textarea').should('have.value',’value is correct’)
// Check length
cy.get('li.selected').should('have.length', 3)
Find Elements
// Get Element (returns Cypress Chainer object)
cy.get(‘#cssSelector)
// Find elements off parent element
cy.get(‘#cssSelector).find(‘#anotherSelector’)
// Return the first element from array of elements
cy.get('nav list’).first()
// Iterate through array of elements
cy.get('nav list’).each(() => {...})
// Create alias for element
cy.get('table').find('tr').as('rows')
cy.get('@rows').first().click()
// Get the element that contains the passed text
cy.get(‘button’).contains(‘Click me’)
The examples

Simple login page using html/javascript/cypress - link


Vuejs app testing: unit & cypress - link
Jest/vitetest examples - link

38
Introduction to TypeScript

TypeScript is a programming language developed and maintained by Microsoft.


It is a strict syntactical superset of JavaScript and adds optional static typing to the language.
TypeScript is designed for the development of large applications and transcompiles to
JavaScript.
As TypeScript is a superset of JavaScript, existing JavaScript programs are also valid TypeScript
programs.
TypeScript may be used to develop JavaScript applications for both client-side and server-side
execution (as with Node.js).
Typescript & Javascript
TypeScript builds on top of JavaScript. First, we write the TypeScript code. Then, compile the
TypeScript code into plain JavaScript code using a TypeScript compiler.
Once you have the plain JavaScript code, you can deploy it to any environments that JavaScript runs.
TypeScript Setup
Node.js – Node.js is the environment on which we will run the TypeScript
compiler. Note that we don’t need to know node.js.
TypeScript compiler – a Node.js module that compiles TypeScript into
JavaScript. If you use JavaScript for node.js, you can install the ts-node module. It
is a TypeScript execution and REPL for node.js
Visual Studio Code or VS code – is a code editor that supports TypeScript. VS
Code is highly recommended. However, you can use your favorite editor.
Live Server – allows you to launch a development local Server with the hot reload
feature.
Node.js & Typescript installation
To install node.js, follow these steps:
● Go to the node.js download page.
● Download the node.js version that suits your platform i.e., Windows, macOS, or Linux.
● Execute the downloaded node.js package or execution file. The installation is quite
straightforward.
To install the TypeScript compiler, you launch the Terminal on macOS or Linux and Command Prompt
on Windows and type the following command:
npm install -g typescript
After the installation, you can type the following command to check the current version of the
TypeScript compiler:
tsc --v (Version 5.4.2)
Typescript to Javascript
enum Color { var Color;
RED = "red", (function (Color) {
BLUE = "blue", Color["RED"] = "red";
GREEN = "green", Color["BLUE"] = "blue";
} Color["GREEN"] = "green";
})(Color || (Color = {}));
enum Engine {
V6 = "v6", var Engine;
V8 = "v8", (function (Engine) {
ELECTRIC = "electric", Engine["V6"] = "v6";
} Engine["V8"] = "v8";
Engine["ELECTRIC"] = "electric";
class Car { })(Engine || (Engine = {}));
color: Color;
engine: Engine; var Car = /** @class */ (function () {
brand: string; function Car(color, engine, brand,
model: string; model) {
this.color = color;
constructor(color: Color, engine: Engine, brand: this.engine = engine;
string, this.brand = brand;
model: string) { this.model = model;
this.color = color; }
this.engine = engine; return Car;
this.brand = brand; }());
this.model = model;
} var myCar = new Car(Color.BLUE,
} Engine.ELECTRIC, "Tesla", "Model 3");
const myCar = new Car(Color.BLUE, Engine.ELECTRIC,
"Tesla", "Model 3");

tsc app.ts (generates app.js)


Typescript: Hello World

let message: string = 'Hello, World!';


// create a new heading 1 element
let heading = document.createElement('h1');
heading.textContent = message;
// add the heading the document
document.body.appendChild(heading);

tsc app.ts (generates app.js)


index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TypeScript: Hello, World!</title>
</head>
<body>
<script src="app.js"></script>
</body>
</html>
Types in TypeScript

Boolean
The most basic datatype is the simple true/false value, which JavaScript and
TypeScript call a boolean value.
let isDone: boolean = false;
Types in TypeScript

Number
As in JavaScript, all numbers in TypeScript are either floating point values or
BigIntegers. These floating point numbers get the type number, while
BigIntegers get the type bigint. In addition to hexadecimal and decimal literals,
TypeScript also supports binary and octal literals introduced in ECMAScript 2015.
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;
let big: bigint = 100n;
Types in TypeScript

String
Just like JavaScript, TypeScript also uses double quotes (") or single quotes (') to
surround string data.
let color: string = "blue";
color = 'red';
We can also use template strings, which can span multiple lines and have
embedded expressions. These strings are surrounded by the backtick/backquote
(`) character, and embedded expressions are of the form ${ expr }.
Types in TypeScript

Array
TypeScript, like JavaScript, allows you to work with arrays of values. Array types
can be written in one of two ways. In the first, you use the type of the elements
followed by [] to denote an array of that element type:
let list: number[] = [1, 2, 3];
The second way uses a generic array type, Array<elemType>:
let list: Array<number> = [1, 2, 3];
Types in TypeScript
Tuple
Tuple types allow you to express an array with a fixed number of elements whose types are
known, but need not be the same.
// Declare a tuple type
let x: [string, number];
// Initialize it
x = ["hello", 10]; // OK
// Initialize it incorrectly
x = [10, "hello"]; // Error
Types in TypeScript

When accessing an element with a known index, the correct type is retrieved:
console.log(x[0].substring(1)); // OK
console.log(x[1].substring(1)); // error:
Property 'substring' does not exist on type 'number'.

x[3] = "world";
Tuple type '[string, number]' of length '2' has no element at index '3'.
Types in TypeScript
Enum
A helpful addition to the standard set of datatypes from JavaScript is the enum. As in languages like
C#, an enum is a way of giving more friendly names to sets of numeric values.
enum Color {
Red,
Green,
Blue,
}
let c: Color = Color.Green;
By default, enums begin numbering their members starting at 0.
Types in TypeScript
Unknown
Values may come from dynamic content – e.g. from the user – or we may want to intentionally
accept all values in our API. In these cases, we want to provide a type that tells the compiler and
future readers that this variable could be anything, so we give it the unknown type.
let notSure: unknown = 4;
notSure = "maybe a string instead";
// OK, definitely a boolean
notSure = false;
declare const maybe: unknown;
// 'maybe' could be a string, object,
boolean, undefined, or other types
const aNumber: number = maybe;
Type 'unknown' is not assignable to type
'number'.
Types in TypeScript
Any
In some situations, not all type information is available or its declaration would take an inappropriate
amount of effort. These may occur for values from code that has been written without TypeScript or
a 3rd party library. In these cases, we might want to opt-out of type checking. To do so, we label
these values with the any type:
declare function getValue(key: string): any;
// OK, return value of 'getValue' is not checked
const str: string = getValue("myString");
Unlike unknown, variables of type any allow you to access arbitrary properties, even ones that
don’t exist.
TypeScript 3.0 introduces a new top type unknown. unknown is the type-safe counterpart of any.
Anything is assignable to unknown, but unknown isn’t assignable to anything but itself
and any without a type assertion or a control flow based narrowing. Likewise, no operations are
permitted on an unknown without first asserting or narrowing to a more specific type.
Types in TypeScript

Void
void is a little like the opposite of any: the absence of having any type at all. You may
commonly see this as the return type of functions that do not return a value:
function warnUser(): void {
console.log("This is my warning message");
}
Declaring variables of type void is not useful because you can only assign null (only if --
strictNullChecks is not specified, see next section) or undefined to them:
let unusable: void = undefined;
// OK if `--strictNullChecks` is not given
unusable = null;
Types in TypeScript

Null and Undefined


In TypeScript, both undefined and null actually have their types named undefined and null
respectively. Much like void, they’re not extremely useful on their own:

// Not much else we can assign to these variables!


let u: undefined = undefined;
let n: null = null;
Types in TypeScript
Never
The never type represents the type of values that never occur.
For instance, never is the return type for a function expression or an arrow function expression
that always throws an exception or one that never returns.
Variables also acquire the type never when narrowed by any type guards that can never be true.

// Function returning never must not have a reachable end point


function error(message: string): never {
throw new Error(message);
}
// Inferred return type is never
function fail() {
return error("Something failed");
}
Types in TypeScript
Object
object is a type that represents the non-primitive type, i.e. anything that is not number, string,
boolean, bigint, symbol, null, or undefined.

With object type, APIs like Object.create can be better represented. For example:

declare function create(o: object | null): void;

// OK
create({ prop: 0 });
create(null);

create("string"); //error
TypeScript functions

function name(parameter: type, parameter:type,...): returnType {


// do something
}
Unlike JavaScript, TypeScript allows you to use type annotations in
parameters and return value of a function.

function add(a: number, b: number): number {


return a + b;
}

When you call the add() function, the TypeScript compiler will check each
argument passed to the function to ensure that they are numbers.
TypeScript functions

TypeScript compiler will match the number of parameters with their types and the return type.

The following example shows how to assign a function to the add variable:

add = function (x: number, y: number) {


return x + y;
};
Also, you can declare a variable and assign a function to a variable like this:

let add: (a: number, b: number) => number =


function (x: number, y: number) {
return x + y;
};
TypeScript Optional Parameters

In TypeScript, the compiler checks every function call and issues an error in the
following cases:
● The number of arguments is different from the number of parameters
specified in the function.
● Or the types of arguments are not compatible with the types of function
parameters.
TypeScript Optional Parameters

function multiply(a: number, b: number, c?: number): number {

if (typeof c !== 'undefined') {


return a * b * c;
}
return a * b;
}
The optional parameters must appear after the required parameters in the
parameter list.
TypeScript default parameters

function name(parameter1=defaultValue1,...) {
// do something
}
In this syntax, if you don’t pass arguments or pass the undefined into the
function when calling it, the function will take the default initialized values for
the omitted parameters. For example:
function applyDiscount(price, discount = 0.05) {
return price * (1 - discount);
}
console.log(applyDiscount(100)); // 95
TypeScript function overloadings

In TypeScript, function overloadings allow to establish the relationship between


the parameter types and result types of a function.
function addNumbers(a: number, b: number): number {
return a + b;
}
function addStrings(a: string, b: string): string {
return a + b;
}
Function overloading with
optional parameters
When we overload a function, the number of required parameters must be
the same. If an overload has more parameters than the other, you have to make
the additional parameters optional. For example:
function sum(a: number, b: number): number;
function sum(a: number, b: number, c: number): number;
function sum(a: number, b: number, c?: number): number {
if (c) return a + b + c;
return a + b;
}
Classes
TypeScript class adds type annotations to the properties and methods of the class. The
following shows the Person class in TypeScript:

class Person {
firstName: string;
lastName: string;
constructor(firstName: string, lastName: string) {
this.firstName = firstName;
this.lastName = lastName;
}

getFullName(): string {
return `${this.firstName} ${this.lastName}`;
}
}
let person = new Person('John', 'Smith');
TypeScript Access Modifiers

Access modifiers change the visibility of the properties and methods of a class.
TypeScript provides three access modifiers:
private
protected
public
Note that TypeScript controls the access logically during compilation time,
not at runtime.
TypeScript Access Modifiers

The private modifier


The private modifier limits the visibility to the same-class only.
The public modifier
The public modifier allows class properties and methods to be accessible from all locations. If we
don’t specify any access modifier for properties and methods, they will take the public
modifier by default.
The protected modifier
The protected modifier allows properties and methods of a class to be accessible within same
class and within subclasses.
When a class (child class) inherits from another class (parent class), it is a subclass of the parent
class.
TypeScript Access Modifiers

class Person {

constructor(private firstName: string, protected lastName: string) {


this.firstName = firstName;
this.lastName = lastName;
}

getFullName(): string {
return `${this.firstName} ${this.lastName}`;
}
}
TypeScript readonly

TypeScript provides the readonly modifier that allows you to mark the properties of a class
immutable. The assignment to a readonly property can only occur in one of two places:

● In the property declaration.


● In the constructor of the same class.

class Person {
readonly birthDate: Date;

constructor(birthDate: Date) {
this.birthDate = birthDate;
}
}
Readonly vs. const

readonly
Use for Class properties Variables

const
Initialization In the declaration or in the constructor of the same class
In the declaration
TypeScript inheritance

TypeScript supports inheritance like ES6:

class Employee extends Person {


//..
}
TypeScript Static Methods and
Properties

Unlike an instance property, a static property is shared among all instances of a


class.

class Employee {
static headcount: number = 0;

public static getHeadcount() {


return Employee.headcount;
}
}
...
Employee.headcount++;
Employee.getHeadcount();
TypeScript abstract classes

An abstract class is typically used to define common behaviors for derived classes
to extend.
Unlike a regular class, an abstract class cannot be instantiated directly.
abstract class Employee {
constructor(private firstName: string, private lastName: string) {
}
abstract getSalary(): number
}
TypeScript abstract classes

class FullTimeEmployee extends Employee {


constructor(firstName: string, lastName: string, private salary: number) {
super(firstName, lastName);
}
getSalary(): number {
return this.salary;
}
}
TypeScript interfaces

The following uses an interface called Person that has two string properties:
interface Person {
firstName: string;
lastName: string;
}
By convention, the interface names are in the camel case. They use a single
capitalized letter to separate words in there names. For example, Person,
UserProfile, and FullName.
TypeScript interfaces

function getFullName(person: Person) {


return `${person.firstName} ${person.lastName}`;
}
let john = {
firstName: 'John',
lastName: 'Smith'
};
console.log(getFullName(john));
Optional properties

An interface may have optional properties. To declare an optional property, you


use the question mark (?) at the end of the property name in the declaration, like
this:

interface Person {
firstName: string;
middleName?: string;
lastName: string;
}
Function types
To describe a function type, we assign the interface to the function signature that contains the
parameter list with types and returned types. For example:

interface StringFormat {
(str: string, isUpper: boolean): string
}

let format: StringFormat;

format = function (str: string, isUpper: boolean) {


return isUpper ? str.toLocaleUpperCase() : str.toLocaleLowerCase();
};

console.log(format('hi', true)); // HI
Class Types

For example, the following Json interface can be implemented by any unrelated
classes:
interface Json {
toJSON(): string
}
class Person implements Json {
constructor(private firstName: string,
private lastName: string) {
}
toJson(): string {
return JSON.stringify(this);
}
}
Interfaces extending
interface Mailable {
send(email: string): boolean
queue(email: string): boolean
}
interface FutureMailable extends Mailable {
later(email: string, after: number): boolean
}
An interface can extend multiple interfaces, creating a combination of all the interfaces.
TypeScript Generics
TypeScript generics allow to write the reusable and generalized form of functions, classes, and
interfaces. In this tutorial, you’re focusing on developing generic functions.

function getRandomElement<T>(items: T[]): T {


let randomIndex = Math.floor(Math.random() * items.length);
return items[randomIndex];
}

let numbers = [1, 5, 7, 4, 2, 9];


let colors = ['red', 'green', 'blue'];

console.log(getRandomAnyElement(numbers));
console.log(getRandomAnyElement(colors));
Typescript Singleton
class MySingleton { const myInstance1: MySingleton =
MySingleton.getInstance();
static instance: MySingleton; const myInstance2: MySingleton =
static a: number = 0; MySingleton.getInstance();
private constructor() {
const myInstance3: MySingleton =
MySingleton.getInstance();
console.log("constructor called!");
} const myInstance4: MySingleton =
MySingleton.getInstance();
public static getInstance(): MySingleton
MySingleton.logic(); // 4
{
MySingleton.a++; A = new MySingleton()
if (!MySingleton.instance) {
MySingleton.instance = new
MySingleton();
}
//The VehicleHandler is "abstract" because noone
Typescript Factory is going to instantiate it
//We want to extend it and implement the
interface Vehicle { abstract method
move(): void abstract class VehicleHandler {
}
//This is the method real handlers need to
//The classes we care about, the "move" method implement
is where our "business logic" would live public abstract createVehicle(): Vehicle
class Car implements Vehicle {
//This is the method we care about, the rest of
public move(): void { the business logic resides here
console.log("Moving the car!") public moveVehicle(): void {
} const myVehicle = this.createVehicle()
} myVehicle.move()
}
class Bicycle implements Vehicle { }

public move(): void { //Here is where we implement the custom object


type InternalState = {
event: String
}
Typescript Observer
abstract class Observer {
abstract update(state:InternalState): void
}

abstract class Observable {

protected observers: Observer[] = [] //the


list of observers
protected state:InternalState = { event: "" }
//the internal state observers are watching

public addObserver(o:Observer):void {
this.observers.push(o)
}

protected notify() {

You might also like