Categories
JavaScript TypeScript

Introduction to TypeScript Functions — This Object and Overloads

Functions are small blocks of code that take an input and either return an output or have side effects, which means that if modifies variables outside the function. We need functions to organize code into small blocks that are reusable. Without functions, if we want to re-run a piece of code, we have to copy it to different places. Functions are critical to any TypeScript program. In this part of the series, we continue to look at different parts of TypeScript functions, including how to deal with the this object with TypeScript, and overloading functions.


This Object

If this is referenced in the regular function declared with the function keyword, the this object isn’t set inside an arrow function to the function that has the this inside. If an arrow function is inside a constructor, then this is set to the new object. If it’s not inside an object, then this inside the arrow function is undefined in strict mode. this will be set to the base object if the arrow function is inside an object. However, we always get the window object if we reference this in an arrow function. For example, the following code wouldn’t compile and run since TypeScript doesn’t allow our code to have the global variable as the value for this:

const fn = () => this  
console.log(fn());

We get the window object logged when console.log is run. Likewise, if we ran this:

let obj = {}  
obj.f = () => {  
  return this;  
};  
console.log(obj.f());

We get the same thing as we got before. This is in contrast to the traditional functions declared with the function keyword. Let’s see what happens if we replace the functions above with traditional functions in the code above, as in the following code:

const fn = function() {  
  return this  
};  
console.log(fn);

Now, if we have noImplicitThis flag on in our tsconfig.json, we get the following error from the TypeScript compiler: 'this' implicitly has type ‘any’ because it does not have a type annotation.(2683)

We’re closer to getting our code working, but it’s still not going to compile. To fix this error, we need to put a fake parameter, this: void, in the function signature, as in the code below:

const fn = function(this: void) {  
    return this;  
};  
console.log(fn);

With the code above, we make the this variable unusable. If we want to use it for something, we can add an explicit type for this instead of void, to make it do something. For example, if we want to make a constructor object, we can write something like the following code:

In the code above, we created an interface called Person to add a data type to the this object in the greet function in the person object. When we call the greet function, the this parameter is ignored since we placed it as the first parameter. TypeScript only looks at the type of this in the parameter and will not expect us to call the greet function by passing in an argument for this. After defining the person object, we can then assign values to the name and age properties outside it. We already met the requirements listed in the interface when we’re defining the person object, but we should also assign some meaning value to it so we can use the greet function.

Then, when we run we run the console.log in the last line of the example above, we get Hi Jane. You’re 20 years old. We’ve successfully created a data type for this, so there won’t be any ambiguity as to what the value of this is. This helps developers understand what this has in the code since this is one of the more confusing aspects of JavaScript. In plain JavaScript, this can take on different values depending on where the this keyword is located in the code. In traditional functions, this’s value would be the function itself. Arrow functions do not change the value of this, so whatever it was outside is the same as whatever it is inside the arrow function.

With TypeScript, we can’t use the this and traditional functions to create classes. For example, if we write:

Then we would get the error Cannot find name ‘Person’. Did you mean ‘person’?(2552) and the code won’t compile. TypeScript doesn’t let us use traditional functions as classes. To use make classes, we must use the class syntax.


‘this’ Parameters in Callbacks

For callback functions used for event listeners, the callback functions that we pass in should be typed in an interface. For example, for setting the type of custom input control components, we can write something like Tthis:

interface InputElement {  
  addKeyUpListener(onclick: (this: void, e: Event) => void): void;  
}

Then, when people that use the control, then they can write something like this for it to run:

What if developers that use the library try to reference this, as in the following code?:

In this case, the TypeScript compiler will throw an error since this is marked with the void type in the InputElement interface.


Function Overloads

Overloading a function is creating functions with the same name, but with different signatures. This isn’t allowed in JavaScript since functions are objects and we can’t re-declare the same object multiple times. However, since TypeScript is strongly typed, which is the opposite of the dynamic nature of JavaScript, it has to find a way to accommodate the dynamic aspects of JavaScript. To do this, TypeScript provides us a way to overload functions with different signatures. To overload functions with TypeScript, we just have to write multiple function signatures with the same name before defining the actual function with that name. For example, we can write something like this:

function getPerson(person: { name: string, age: number }): { name: string, age: number };  
function getPerson(person: { name: string }): { name: string };  
function getPerson(person: any): any {  
  return person;  
}

With the code above, we have a getPerson function that can either accept an object with the properties name and age , or just the property name. The return type, which is after the colon, can either be an object with both the name and age properties, or an object with just the name property. This is what we have in the first three lines of the code example above, where we just define the signatures we want for our getPerson function.

Then in the actual getPerson function definition, we have the actual function definition. We annotate the type of the parameter and return as any , which is OK because we already defined the parameters and return types that the getPerson accepts and returns respectively. We can call the getPerson, as in the code below:

console.log(getPerson({ name: 'Jane', age: 20 }));  
console.log(getPerson({ name: 'Jane' }));

From the console.log statements above, we get:

{name: "Jane", age: 20}  
{name: "Jane"}

If we try to call it with an argument that we didn’t define in the signature like: console.log(getPerson({})) we get a No overload matches this call error.

The main way to deal with the this object in traditional functions is to pass it in as the first parameter of a function and then set a type to it by defining an interface for the type. TypeScript will ignore the this parameter and treat it as if it doesn’t exist. It’s only used for setting the data type of this. We can overload functions in TypeScript, which isn’t allowed in JavaScript. To do this, we just define different signatures for the function and give them the same name, then define the function with the same name after we defined the signatures that our function will accept.

Categories
JavaScript JavaScript Basics

How to Copy Objects in JavaScript

Copying objects means making a new object reference to an object that has the same contents as the original. It is used a lot to prevent modifying the original data while you assign a variable to another variable. Because if you assign a variable to a new one, the new one has the same reference as the original object.

There are a few ways to clone objects with JavaScript. Some functions do shallow copying which means that not all levels of the object are copied, so they may still hold the reference the original object. A deep copy copies everything so that nothing references the original object, eliminating any confusion which arises from shallow copy.

Clone Object Using Built in JavaScript Functions

Is you assign a object to another variable, it just assigns the reference to the original object, so both variables will point to the original object. When one of the variables are manipulated, both will be updated. This is not always the desired behavior. To avoid this, you need to copy a object from one variable to another.

In JavaScript, this is easy to do. To shallow copy an object, we can use Objec.assign() , which is built into the latest versions of JavaScript. This function does a shallow copy, which means it only copies the top level of an object, while the deeper levels remain linked to the original object reference. This may not be desired if there is nested in your original object.

Here is an example of how to use Object.assign :

const a = { foo: {bar: 1 }}  
const b = Object.assign({}, a) // get a clone of a which you can change with out modifying a itself

You can also clone an array like this:

const a = \[1,2,3\]  
const b = Object.assign(\[\], a) // get a clone of a which you can change with out modifying a itself

To do a deep copy of a object without a library, you can JSON.stringify then JSON.parse :

const a = { foo: {bar: 1, {baz: 2}}  
const b = JSON.parse(JSON.strinfy(a)) // get a clone of a which you can change with out modifying a itself

This does a deep copy of an object, which means all levels of an object are cloned instead of referencing the original object.

JSON.parse and JSON.stringify only works with plain objects, which means it cannot have functions and other code that runs.

With ES6, you can also use object destructuring to shallow clone objects, like so:

const a = { foo: {bar: 1}}  
const b = {...a} // get a clone of a which you can change with out modifying a itself

Clone Object Using Third Party Libraries

There are many third parties which can do the same things. Lodash has _.clone and _.cloneDeep functions for shallow and deep copy. Underscore has a _.clone function for shallow copy.

Cloning objects is common operation that is easy to do with JavaScript. Now you can avoid bugs by not modifying objects that you are not intending to modify by copying them and then modify the copied object.

Categories
JavaScript JavaScript Basics

How to Check if a JavaScript Object is an Array

There are a few simple ways to check if an object is an array.

Array.isArray

The simplest and easiest way is to use Array.isArray , which are available in most recent browsers, IE9+, Chrome, Edge, Firefox 4+, etc. It is also built into all versions of Node.js. It checks whether any object or undefined is an array.

To use it, do the following:

const arr = [1,2,3,4,5];
const isArrAnArray = Array.isArray(arr); // true
const obj = {};
const isObjAnArray = Array.isArray(obj); // false
const undef = undefined;
const isUndefinedAnArray = Array.isArray(undef); // false

Alternatives

Alternatives include using instanceOf , checking if the constructor is an array or checking if an object’s prototype has the word Array.

Using instanceOf , you can do:

const arr = [1,2,3,4,5];
const isArray = (arr)=>{
  return arr.constructor.toString().indexOf("Array") > -1;
}
console.log(isArray(arr)) // true

Similarly, by checking an object’s prototype, you can do:

const arr = [1,2,3,4,5];
const isArray = (arr)=>{
  return Object.prototype.toString.call(arr) === '[object Array]';
}
console.log(isArray(arr)) // true

Third Party Libraries

Underscore and Lodash also have equivalent array check functions:

const arr = [1,2,3,4,5];
const isArraAnArray _.isArray(arr); // true
Categories
JavaScript Nodejs

How to Add Twitter Sign In to Your Node.js Back End

Twitter uses the standard OAuth for authentication, which means you incorporate a standardized way of logging in if you use Twitter sign in.

In Node.js, it is very easy to add Twitter sign in to an Express web app.


Getting Started

First, you have to make an Express app. Express is a routing library with a lot of add-ons built for easy web development.

There are many Express app boilerplates available on the web. There is also an Express code generator from the makers of the Express framework.

Using the latest Node.js versions, you can run npx express-generator.

If npx is not available, you can install express-generator globally and run that:

$ npm install -g express-generator  
$ express

Make a folder for your project and follow the instructions.

To make the example simple, this app will provide the redirect URL that you get after providing the consumer key and request token for the Angular app.

Then, after the user goes through the Twitter sign in, it will redirect back to the Angular app, which will then call the Express API to save the OAuth access token and the OAuth access token secret to a database.

We need to make an entry point file for Express.

We need to install express-session, express-logger, cookie-parser, and cors for saving sessions, logging, parsing cookies, and allowing external requests for our Angular app, respectively.

babel-register and bale-polyfill are required to use the latest JavaScript features in our Node.js web app.

To save the secrets, use the [dotenv](https://www.npmjs.com/package/dotenv) library. With this, the secrets will be read from the .env file, rather than hard coding them into the code, which is very bad secret practice.

To get the Twitter keys, you have to apply for a developer account at https://developer.twitter.com/. You will then get the keys and secrets required, which you will put into the .env file.

The .env file should be a key-value list, like this:

TWITTER_CONSUMER_KEY=''  
TWITTER_CONSUMER_SECRET=''  
TWITTER_CALLBACK_URL='http://localhost:4200/settings'
SESSION_SECRET=''

I will call the entry point file app.js .

To run this, go to your project folder and run node app.js:

Then, we need the oauth library to make an oauth.OAuth object which will allow the Express app to get the request token and request token secret.

Add a controllers folder in the same level as app.js.

Then, add sessionsController.js into the controllers folder.

Add the following to sessionsController.js:

The connect route will send the Twitter sign-in URL as the redirect URL.

Then, the Angular app will call the saveAccessTokens route to store the OAuth access token and its secret in the session.


Angular CLI

To build the Angular app, you need the Angular CLI.

To install it, run npm i -g @angular/cli in your Node.js command prompt. Then, run ng new frontend to generate the skeleton code for your front end app.

Also, install @angular/material according to the Angular documentation.

After that, replace the default app.module.ts with the following:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {
  MatButtonModule,
  MatTableModule,
  MAT_DIALOG_DEFAULT_OPTIONS,
} from '@angular/material';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SettingsPageComponent } from './settings-page/settings-page.component';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { SessionService } from './session.service';
import { HttpReqInterceptor } from './http-req-interceptor';
@NgModule({
  declarations: [
    AppComponent,
    SettingsPageComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    MatButtonModule,
    FormsModule,
    HttpClientModule,
  ],
  providers: [
    SessionService,
    {
      provide: HTTP_INTERCEPTORS,
      useClass: HttpReqInterceptor,
      multi: true
    },
    UserService,
    TweetsService,
  ],
  bootstrap: [AppComponent],
})
export class AppModule { }

We need to use Angular’s HTTP client to connect to our Express routes to get the redirect URL and get the access token from the redirect after logging in with Twitter, then send it back to our route.

To do this, run ng g service session.

This will create session.service.ts:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from 'src/environments/environment';
@Injectable({
  providedIn: 'root'
})
export class SessionService {
  constructor(private http: HttpClient) { }
  getRedirectUrl() {
  return this.http.get(`${environment.apiUrl}/sessions/connect`)
}
  saveAccessToken(oauthToken: string, oauthVerifier: string) {
    return this.http.get(`${environment.apiUrl}/sessions/saveAccessTokens?oauth_token=${oauthToken}&oauth_verifier=${oauthVerifier}`)
  }
}

In here, environment.apiUrl is the URL to our API, which is specified in environment.ts.

Now, we need a page with a button that calls our Express route to get the redirect URL.

Run ng g component settingsPage to create settings-page.component.ts and settings-page.component.html, which is where the button will be placed.

Add the following to settings-page.component.html:

<div>  
  <button mat-raised-button (click)='redirectToTwitter()'>Connect to Twitter Account</button>  
</div>

Then, add the following settings-page.component.ts:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { SessionService } from '../session.service';
@Component({
  selector: 'app-settings-page',
  templateUrl: './settings-page.component.html',
  styleUrls: ['./settings-page.component.scss']
})
export class SettingsPageComponent implements OnInit {
  constructor(
    private activatedRoute: ActivatedRoute,
    private sessionService: SessionService,
  ) {
    this.activatedRoute.queryParams.subscribe(params => {
      const oauthVerifier = params['oauth_verifier'];
      const oauthToken = params['oauth_token'];
      if (oauthToken && oauthVerifier) {
        this.saveAccessToken(oauthToken, oauthVerifier);
      }
    });
  }
  ngOnInit() {}
  saveAccessToken(oauthToken: string, oauthVerifier: string) {
    this.sessionService.saveAccessToken(oauthToken, oauthVerifier).subscribe(res => {
    alert('Token saved');
    })
  }
  redirectToTwitter() {
    this.sessionService.getRedirectUrl().subscribe((res: any) => {
      location.href = res.redirectUrl;
    })
  }
}

After adding the code above, you get a button that, after you click it, will go to the Twitter sign-in page.

Then, once Twitter sign in succeeds, you will be redirected to the same page with the OAuth access token and verifier, which will be sent to our Express API and stored in the session.


Token Saved

You will get Token saved message once it succeeds.

In the end, this is the workflow you should get:

  1. First, you get the connect button:

https://thewebdev.info/wp-content/uploads/2020/05/connect.png

  1. Then, you are redirected to the Twitter login:

https://thewebdev.info/wp-content/uploads/2020/05/twitter-login.png

  1. Finally, you are redirected back with the OAuth access token and verifier, and with those, you get the access token and secret which will be stored to the session.

If that succeeds, the saveAccessTokens route will return a successful response, which will then trigger the Angular app to alert Token saved.

Categories
JavaScript TypeScript

Introduction to TypeScript Classes — Static Properties, Abstract Classes and More

Classes in TypeScript, as in JavaScript, are a special syntax for its prototypical inheritance model that’s a comparable inheritance in class-based object oriented languages. Classes are just special functions added to ES6 that are meant to mimic the class keyword from these other languages.

In JavaScript, we can have class declarations and class expressions because they’re just functions. So like all other functions, there are function declarations and function expressions. This is the same with TypeScript. Classes serve as templates to create new objects. TypeScript extends the syntax of classes of JavaScript and then adds its own twist to it. In this piece, we’ll look at static properties, abstract classes, and constructor functions.


Static Properties

With TypeScript, we can designate members as instance variables, which don’t have the keyword static before them, and static members, which have the keyword static keyword before them.

Static members can be accessed without having the class instantiated. Of course, this is given to the access modifiers that are designated for the member. So public static members can be accessed directly from outside the class. Private static members can only be used within the class, and protected members can be accessed by a class the member is defined in and also by subclasses of that class.

The static keyword can be used by both fields and methods. For example, we can use it like in the following code:

class Person {  
  static numPeople = 0;    
  constructor(name: string) {  
    Person.numPeople++;  
  }  
  static getNumPeople() {  
    return this.numPeople;  
  }  
}

const john = new Person('John');  
const jane = new Person('Jane');  
console.log(Person.numPeople);  
console.log(Person.getNumPeople());

In the code above, every time we instantiate the Person class, we increase the static property numPeople by one. Since static properties are shared by all instances of the class and don’t belong to any one instance, we can access numPeople directly by using Person.numPeople.

Likewise, we have a static method, getNumPeople, we can call directly without instantiating the Person class. Therefore, when we get the numPeople by using Person.numPeople and call the Person.getNumPeople(), then the value 2 is returned for both.

Since the members are static, the values is part of a class and not part of any instance, so even if the instances are destroyed the values will be kept. This is different from instance variables, which are accessed from the this inside the class and the variable with the instance of the class outside the class.


Abstract Classes

TypeScript has abstract classes, which are classes that have partial implementation of a class and in which other classes can be derived from. They can’t be instantiated directly.

Unlike interfaces, abstract classes can have implementation details for their members. To declare an abstract class, we can use the abstract keyword. We can also use the abstract keyword for methods to declare abstract methods, which are implemented by classes that derive from an abstract class.

Abstract methods don’t contain implementations of the method. It’s up to the subclasses that derive from the abstract class to implement the method listed. They may also, optionally, include access modifiers.

We can use abstract classes and methods as demonstrated in the following code:

abstract class Person {  
  name: string;  
  age: number;  
  constructor(name: string, age: number) {  
    this.name = name;  
    this.age = age;  
  } abstract getName(): string;  
  abstract getAge(): number;  
}

class Employee extends Person{  
  constructor(name: string, age: number) {  
    super(name, age);  
  } 

  getName() {  
    return this.name;  
  } 

  getAge() {  
    return this.age;  
  }  
}

let employee = new Employee('Jane', 20);  
console.log(employee.getName());  
console.log(employee.getAge());

In the code above, we have the abstract Person class, which has the abstract methods getName and getAge.

As we can see, the abstract methods only have signatures in them. The actual implementation of the methods are in the Employee class, which extends the Person class.

We have the actual implementation of the getName and getAge methods in the Employee class.

TypeScript checks the method signature and the return type of the class, so we must be implementing the abstract methods as it’s outlined in the abstract class. This means that in the example above, the getName method must take no parameters and must return a string.

Likewise, the getAge method must take no parameters and must return a number. After the abstract methods have been implemented, we can call them normally like any other method.


Constructor Functions

When we declare a TypeScript, we’re declaring multiple things at the same time. We’re declaring an instance of the class, which is the entity with the code preceded with the class keyword. For example, we can write:

class Employee{  
  name: string;  
  age: number;  
  constructor(name: string, age: number) {  
    this.name = name;  
    this.age = age;  
  }
}  
let employee: Employee = new Employee('Jane', 20);

In the last line of the code snippet above, we’re using Employee as the type of the instances of the class Employee.

Also, we’re creating another value we call a constructor function. This is the function that’s called when the new keyword is being used to create a new instance of the class.

If we compile the TypeScript code above to ES5 or earlier, we can see we get something like the following code generated:

"use strict";  
var Employee = /** @class (function () {  
    function Employee(name, age) {  
        this.name = name;  
        this.age = age;  
    }  
    return Employee;  
}());  
var employee = new Employee('Jane', 20);

In the code above, the constructor function is the following code:

function Employee(name, age) {  
  this.name = name;  
  this.age = age;  
}

We have this because in JavaScript, no matter what version we’re using, a class is just the syntactic sugar for constructor functions. The inheritance model of TypeScript just extends from JavaScript. It didn’t change the inheritance model of JavaScript since it’s supposed to be 100% compatible with existing JavaScript code so existing JavaScript code can be adopted to use TypeScript.

In TypeScript, we can get the type of the constructor function with the typeof operator. It’s different from its usage in JavaScript as it has been extended to get the type of the constructor function of a class. If we run the following code …

class Employee{  
  name: string;  
  age: number;  
  static companyName: string = 'ABC Company';  
  constructor(name: string, age: number) {  
    this.name = name;  
    this.age = age;  
  }}

let employeeConstructor: typeof Employee = Employee;  
console.log(Employee.companyName);  
console.log(employeeConstructor.companyName);

… it makes sense when we get the value of the static member companyName logged in both console.log statements. As we can see from the compiled output …

"use strict";  
var Employee = /** @class */ (function () {  
    function Employee(name, age) {  
        this.name = name;  
        this.age = age;  
    }  
    Employee.companyName = 'ABC Company';  
    return Employee;  
}());  
var employeeConstructor = Employee;  
console.log(Employee.companyName);  
console.log(employeeConstructor.companyName);

… a JavaScript and TypeScript class are ultimately just functions. The class syntax makes inheritance of JavaScript easier to use since it looks like it’s using class-based inheritance, but it’s actually syntactic sugar on top of the prototypical inheritance model that’s been the same since JavaScript first came out.

TypeScript makes inheritance easy by letting us define abstract classes — where some implementation is done by the abstract and others are done in the subclass that extends the abstract class.

We also have abstract methods that subclasses can implement. Abstract methods only have the signature and return type and no implementation details.

Static members let us define members that are part of the class rather than an instance of the class.

It’s also important to know that the class syntax is ultimately syntactic sugar for the prototypical inheritance model that existed since the beginning of JavaScript. However, now we can put that aside since we can use the syntactic sugar to make it easier to understand and implement inheritance.