Check out our Angular Book Series.

How do I get an Array of all the Keys in a JavaScript Map?

I'm working on an Angular application and want to loop over all the keys in a JavaScript map. A map is a key value pair data type, like an object, but geared for dynamic properties. In the ColdFusion world we called this a structure, and in ActionScript we called it a dictionary, but the concept is the same.

I can create a map and add items to it, like this:


let myMap = new Map();
myMap.set('foo', 'bar');
myMap.set('bar', 'Barbar');
myMap.set('foobar', 'BarbarFooFoo');

You can look at the map like this:

Once it has a set of keys, I can get the keys using this:


myMap.keys();

This is an object, or more specifically an iterator. But, I want the keys as an array.

One trick is to convert the iterator to an array using Array.from():


Array.from( hydratedImageMap.keys() );

A more 'ES6' technique would be to use the spread operator:


[ ...hydratedImageMap.keys() ]

You'll see similar output:

Not all that hard! Get the code here or play with it here.

How do I make a TypeScript property that could have multiple types?

I'm working on an app for a client and as with many apps was displaying a list of items. I needed to loop over this list and display items. Every UI framework has some way to do this.

This was an Angular app using TypeScript, so I making use of TypeScript's statically typed nature. My problem was that the objects in this list could be one of two types, let's call those Type1 or Type2. I was running into errors when transpiling the code. I had defined the type like this on the class:


myItems: Type1[];

This code created an array of Type1 arguments. IT wasn't until later that Type2 was added as a possible value in this list.

When updating the code to accommodate for Type2 I realized that sometimes I was receiving errors by accessing Type2 specific properties on a Type1 argument. What was the solution? I used something called Union types. I set up my value like this:


myItems: (Type1 | Type2)[];

This means that myItems can be a mixed array of Type1 and Type2 values.

That works great as long as all properties that you access in Type1 are also in Type2. If a property that you're accessing in one and not the other exists, then you'll get errors--these were the same errors I started with. I solved that issue by adding blank getters to the class definition:


get mySharedProperty(){ return null};

Far from perfect, but functional for my purposes.

Maybe I should have just created an interface and had both Type1 and Type2 extend it?

How to spy on a Property with Karma?

When writing unit tests, SpyOn, is used to watch and manipulate a method call, potentially returning your own data. This is used to easily mock external component calls so that your unit test can focus on the class in question without worrying about complications or side affects from external dependencies. I found myself in a situation where I had a class and that class had a read only get() property. I was creating my own Angular service wrapper for the Dragula drag and drop library. I was exposing some drop and remove listeners get methods.

I wanted to control the results returned from that get method. This was not a situation where I could set the underlying value because there was no set method. But, spyOn would not work because a get() method is viewed as a property, not a method. The class code was conceptually like this:


export class MyClass {

constructor(private dragula: DragulaService){
}

get dropListener(){
return this.dragula.drop('myDragulaGroup');
}
}

My code was using Angular, so the DragulaService was injected into this component, and the dropListener was exposed via a get.

For the purposes of unit testing, I want complete control over that drop listener Observable. Thankfully, spyOnProperties would give me that control.

The unit test would be a bit like this:


it("Should spy on Observable", () =>
{
const myClassInstance = new MyClass();

let dropObserver: Observable<any>;
const dropObservable: Observable<any> = Observable.create( ( ObserverArg: Observer<any>) => {
dropObserver= ObserverArg;
}

mySpy = spyOnProperty(myClassInstance, 'dropListener', 'get').and.returnValue(dropObservable);

I'm gonna take a quick break to explain spyOnProperty. It takes three parameters:

  • Class: The class instance that contains the property you want to watch.
  • Property: The name of the property being watched.
  • Accessor: The Access Type of the method being watched, in this case get.

Note that we are storing the results of the spyOnProperty in the mySpy variable. This is optional when using spyOn, but for spyOnProperty it is required. The unit test could would continue:


const val = myClassInstance.dropListener;

All that line does is access the dropListener property inside the class, which should trigger the spy. Now we can test against the access:


expect(mySpy ).toHaveBeenCalled();
});

In a more advanced unit test, we could subscribe to the dropListener inside the test, and use dropObserver.next() to trigger the result handler in an async block.

How do you deep copy an array with JavaScript?

The Problem

I was working on an Angular component that accepted an array input and created a drop down from it. As part of our internal architecture the component would add a disabled property to certain items on the input. This would permanently modify the input array, which was cached by the app and used elsewhere. We couldn't have that. We decided to make an internal copy of the array so that our local component changes would not affect the global data store. How do we do that?

Normally when I want to create a deep copy of an object, I turn to Try it here


const object1 = [
{value: 1},
{value: 2},
{value: 3}
];

const object2 = Object.assign({}, object1);

console.log(object1);

console.log(object2);

Take a look at the output:

If you look closely at the output between object 1 and object 2, you'll discover that object2 is no longer an array, it is an object. That was the wrong syntax and not what we intended.

Object.Assign() with an Array

We could use Object.assign() with an array instead of an object, like this:


const object3 = Object.assign([], object1);

That will give us an array. Make sure that they are separate objects:


object1.push({value:4})
console.log(object1);
console.log(object3);

That does solve the issue and we have an array:

It isn't the only way to solve the issue, though.

Use a spread operator

The spread operator will do the same thing.


const object4 = [...object1];
object1.push({value:4})
console.log(object1);
console.log(object4);

I always forget about the spread operator, but it works well. Depending where you look, there are concerns about it's performance over other options. I'm reusing the same screenshot because there is no change:

Use Slice

You can also create a deep copy of an array using array.slice():


const object5 = object1.slice();

object1.push({value:4})

console.log(object1);
console.log(object5);

Repeated screenshot because nothing changed:

This is the way I went with, for no other reason than it was used elsewhere in the code base and it pays to be consistent.

Hopefully you learned something. ;)

Create TypeScript Modules - - Part 8

This is the last in my series of articles intended to introduce you to Typescript. It is bonus material I wrote for my Angular 4 book. This is the last part of the series. Check out part 1, part 2, Part 3, Part 4, Part 5. and Part 6, and Part 7.

When writing a real-world application, it does not make sense to include all the code in a single file. TypeScript supports that by allowing you to expand different functionality into modules.

Create Interface Module

The first thing we're going to do is create a module for the name interface. I put this in a file named IFile.ts:


export interface name {
firstName: string;
middleInitial? : string;
lastName: string;
getName() : string;
};

This looks exactly like the Interface created in the previous exception with the one addition of the export keyword. Export tells the compiler that this class is available for use inside other classes.

Create Class Modules

Now create the Person class:


export class Person implements name {
firstName: string;
middleInitial : string;
lastName: string;
getName() : string {
return this.firstName + ' ' + this.middleInitial + ' ' + this.lastName;
}
}

This also puts the export keyword in front of the class definition. If you try this you'll notice an immediate error. The name is not defined. To define it we'll need to add an import statement:


import {name} from "./IName";

The import statement tells you that the name entity is imported from the IName file and can be used within this class. The path I used, './IName', tells us that the files are in the same directory, however we can use a more elaborate package setup, and most likely you will do that for main applications.

We can create the Pets.ts module in the same manner:


import {name} from "./IName";

export class Pet implements name {
firstName: string;
lastName: string;
type : string;
getName() : string {
return this.firstName + ' ' + this.lastName + ", " + this.type;
}
}

This code mirrors the Person module, with the primary changes being the use of the export keyword before the class definition and the import of the name interface.

The Echo class needs a similar rework:


import {name} from "./IName";

export class Echo {
static readonly messageIntro : string = "Hello"
subjectArray : name[];
private message : string;
constructor(subjects : name[]){
this.subjectArray = subjects;
}
createMessage():void{
this.message = '';
for (let person of this.subjectArray){
this.message += Echo.messageIntro + " " + person.getName() + "<br/>";
}
}
echo():string{
return this.message;
}
}

The functionality remains unchanged. Like the previous classes it uses an export statement to make the class available elsewhere, and an import statement to make use of the name interface.

Rework Main Application

With all the classes stored in separate files, our primary app has become a lot simpler. First, import all the classes:


import {name} from "./IName";
import {Person} from "./Person";
import {Pet} from "./Pet";
import {Echo} from "./Echo";

Then, create the nameArray:


let nameArray : name[] = [];

Now, populate the nameArray:


let jeffryInstance : Person = new Person();
jeffryInstance.firstName = "Jeffry";
jeffryInstance.middleInitial = "A";
jeffryInstance.lastName = "Houser";
nameArray.push(jeffryInstance);

let hercInstance : Pet = new Pet();
hercInstance.firstName = "Hercules";
hercInstance.lastName = "Houser";
hercInstance.type = "Dog";
nameArray.push(hercInstance);

let zeusInstance : Pet = new Pet();
zeusInstance.firstName = "Isadora";
zeusInstance.lastName = "Houser";
zeusInstance.type = "Dragon";
nameArray.push(zeusInstance);

Create an instance of the Echo class:


let echoInstance : Echo = new Echo(nameArray);

Call the createMessage() function:


echoInstance.createMessage();

Finally, output the results:


document.body.innerHTML = echoInstance.echo();

The changes here was, primarily, removing the class and interface definitions and replacing them with imports.

Setup Module Loader

The import statement is not a native JavaScript statement and does not have an easy parallel. To make code like this work in the browser we'll need to use a module loader. There are a few different types of module loaders such as RequireJS or SystemJS. Many people use code tools like Browserify or WebPack to encapsulate away the complexity.

For the purposes of this sample, I'm going to use RequireJS. Open up the index.html file and add this script statement:


<script data-main="requireconfig"
src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js">

</script>

This loads the RequireJS library from a remote CDN. Note that I have completely removed the script tag that loads the hello.js file. The script tag also has a different attribute named data-main with a value of requireconfig. This property tells Require that whenever it has completed loading it should look for the requireconfig.js file. Create that file next:


requirejs.config({
baseUrl: '',
paths: {
app: ''
}
});

This sets up the baseUrl and the paths to the app. Since all our code is in the main dev directory, I set these values to blank. Now, tell RequireJS to load our main application file:


requirejs(['hello']);

Since there are a few different methods of creating modules, we have to tell our TypeScript compiler which one to use. We want it to use the amd approach. When you compile your application add the module flag and specify amd. Use this at the command line:


tsc module amd hello

You'll see this:

Now load the app in the browser:

Congratulations! This series should have given you all the information you need to know to start using TypeScript to build your applications. Check out our book on Angular 4 which uses TypeScript heavily.

Keep up to date by reading DotComIt's Monthly Technical Newsletter

Create an Interface in TypeScript - - Part 7

I'm writing a series of articles about Typescript as extra material to support my upcoming Angular 4 book. This is the seventh part of that series. Check out part 1, part 2, Part 3, Part 4, Part 5. and Part 6.

This section will talk about interfaces. It is not about User interfaces, but rather object-oriented interfaces. An interface is a definition of properties and methods that must be supported by a class which implements this interface. You can think of an interface as the contract between a class instance and a method argument or variable. If they both match the interface they are interchangeable.

Create the Interface

For this sample, we're going to create a name interface. This interface will represent the name of a person and will contain a first name and last name. It will have an optional middle initial and also a method to retrieve the name. Here is the interface:


interface name {
firstName: string;
middleInitial? : string;
lastName: string;
getName() : string;
}

The interface is set up similar to a class or enum. It uses the keyword interface, and the name of the interface--in this case name. The firstName and lastName properties are as normal properties on an object. The middleInitial is an optional property, and that is distinguished by a question mark. Finally, a single method is defined by the interface, getName(). This will be used to return the name. The interface does not contain an implementation, just a definition of the method. That means different classes which extend the interface can have different implementations.

Rework the Echo Class

Let's rework the Echo class to use the interface instead of strings. First create the method stub with the instance variables:


class Echo {
static readonly messageIntro : string = "Hello"
subjectArray : name[];
private message : string;
}

The main change here is that the subject string was replaced with a subjectArray of name types. The constructor:


constructor(subjects : name[]){
this.subjectArray = subjects;
}

The constructor now accepts an array of name instead of a single string. The createMessage() function now loops over the array:


createMessage():void{
this.message = '';
for (let person of this.subjectArray){
this.message += Echo.messageIntro + " " + person.getName() + "<br/>";
}
}

Inside the loop, the interface's getName() function is used to add an element to the output. Finally, the echo() function:


echo():string{
return this.message;
}

The echo function has not changed, it just returns the object instance variable, message.

Implement the Interface with a Class

I'm going to create two classes which implement our name interface contract. One will be for a Person and another for a Pet. First, the Person class:


class Person implements name {
firstName: string;
middleInitial : string;
lastName: string;
getName(): string {
return this.firstName + ' ' + this.middleInitial + ' ' + this.lastName;
}
}

The class is defined with the class keyword followed by the name of the class. Then comes the implements keyword followed by the name of the interface. If you wanted you could list multiple interfaces here.

The firstName, middleInitial, and lastName are created properties on the object, not much different than how they were with the interface definition. The getName() method includes a definition. It concatenates the firstName, middleInitial, And lastName, returning a single string. Now, let's create another class that implements name. This one is called Pet:


class Pet implements name {
firstName: string;
lastName: string;
type : string;
getName(): string {
return this.firstName + ' ' + this.lastName + ", " + this.type;
}
}

This includes the firstName and lastName defined as variables on the class object. A new property is named type, this will represent the type of pet we have. A class can implement properties or methods not included in an interface. The middleInitial is left out, which is okay because that is marked as an optional property in the interface--and my pets don't have middle initials. The getName() method puts together the firstName and lastName, but appends the type to the end.

Create a name Array

We have an interface and two classes that extend it. Let's put all together. Start by creating a names array:


let nameArray : name[] = [];

Now create a new Person instance. This one represents me:


let jeffryInstance : Person = new Person();
jeffryInstance.firstName = "Jeffry";
jeffryInstance.middleInitial = "A";
jeffryInstance.lastName = "Houser";
nameArray.push(jeffryInstance);

The new jeffryInstance of the Person class is added to the nameArray.

Create two pets:


let hercInstance : Pet = new Pet();
hercInstance.firstName = "Hercules";
hercInstance.lastName = "Houser";
hercInstance.type = "Dog";
nameArray.push(hercInstance);

let zeusInstance : Pet = new Pet();
zeusInstance.firstName = "Isadora";
zeusInstance.lastName = "Houser";
zeusInstance.type = "Dragon";
nameArray.push(zeusInstance);

One is for my pet dog, Hercules, and the other is for my pet dragon, Isadora. Both are added to the same nameArray value without issue even though they have different types. The implementation of the interfaces tells the compiler that the nameArray can accept both Pet and Person instances.

Now, create an instance of the Echo class:


let echoInstance : Echo = new Echo(nameArray);

Create the message:


echoInstance.createMessage();

And output the message:


document.body.innerHTML = echoInstance.echo();

Recompile the app and load it in a browser:

It works as expected.

I have one more entry into this introduction to TypeScript series. It will tell you how to create Modules from your class and interface files.

Keep up to date by reading DotComIt's Monthly Technical Newsletter

Create your first TypeScript Class - - Part 6

I'm writing a series of articles about Typescript as extra material to support my upcoming Angular 4 book. This is the sixth part of that series. Check out part 1, part 2, Part 3, Part 4, and Part 5.

This entry will teach you about creating your own classes. A class is like your own variable type with data and functions to process that data.

Create a Class

Create your class stub:


class Echo {
}

This creates a class named Echo. The purpose of this class is to create and store our welcome message. Let's start by creating some properties on the class:


static readonly messageIntro : string = "Hello"
subject : string;
private message : string;

The subject is a relatively normal variable. It is a string that contains the subject of our welcome message. The message is similar, but has the private distinguisher. This means that the message variable is private to the local message. It will contain the final message once it is put together, but is only accessible inside the class, not from code accessing an instance of the class.

The messageIntro is a bit different. We are not able to define constants inside of a TypeScript class, so instead I used the readonly keyword. This means the value will not be changeable, just like a constant. I also define the messageIntro as a static property, which means it exists on the class and not on an instance of the class.

Every class needs a constructor, so create one:


constructor(subject : string){
this.subject = subject;
}

The constructor will be called automatically when we create a new instance of the class with the new keyword. This constructor accepts one argument, the subject. The code just saves the subject argument into the subject variable.

Now, add a createMessage() function:


createMessage():void{
this.message = Echo.messageIntro + " " + this.subject + "<br/>";
}

This concatenates the read only messageIntro variable with the subject and a line break. We had similar code in previous samples, but not encapsulated into a function. The return type of this function is void, meaning nothing is returned.

We'll add one final function to our class:


echo():string{
return this.message;
}

This function returns the complete message. The message value could be blank if the createMessage() function as not called yet, however this will still work.

Now, create an instance of the Echo class:


var echoInstance : Echo = new Echo('World')

This uses the new keyword to create the new instance. You may have seen this in other languages. You can output the subject for testing purposes:


console.log(echoInstance.subject);

You can also try to output the message:


console.log(echoInstance.message);

Since the message is a private variable, you'll see a compile error:

By the same token, we can access the messageIntro static value:


console.log(echoInstance.messageIntro);
console.log(Echo.messageIntro);

Can you guess which line works before trying to compile the code? The second one is the proper way to access static variables. The first one will throw an error:

Our final code is to output the value to the screen:


document.body.innerHTML = echoInstance.echo();

Compile the code--you should see no errors--and load it in a browser:

In a non-sample application, I might try to make my classes more discrete. Since this one adds a line break at the end of the message, it is conflating data processing and display code, something which is undesirable in real world applications.

Review the Generated Code

This is the generated code:


var Echo = (function () {
function Echo(subject) {
this.subject = subject;
}
Echo.prototype.createMessage = function () {
this.message = Echo.messageIntro + " " + this.subject + "<br/>";
};
Echo.prototype.echo = function () {
return this.message;
};
Echo.messageIntro = "Hello";
return Echo;
}());
var echoInstance = new Echo('World');
echoInstance.createMessage();
document.body.innerHTML = echoInstance.echo();

The Echo class is created using an immediately invoked function expression. The static class property is created as an instance variable inside the class--remember that JavaScript doesn't have the concept of readonly or static properties. The subject and message variables are not defined since they do not have default values. They'll be created on the class when they are needed, which is inside the function.

Although beyond the scope of this tutorial, inheritance is supported with TypeScript, so one class can inherit from another.

Keep up to date by reading DotComIt's Monthly Technical Newsletter

Loops and Arrays in TypeScript - Part 5

I'm writing a longer series of articles about Typescript. This will be extra material to support my upcoming Angular 4 book. This is the fifth part of that series. Check out part 1, part 2, Part 3, and Part 4.

This entry will focus on loops and arrays. We'll create an array of strings, and then loop over them with our echo function to welcome multiple people in our HTML page.

Create an Array

The first step is to create an array. You can use this sytnax:


let personArray : string[] = ["Jeffry", "Tom", "John"];

This creates a variable just like other variables we had seen. The key differentiator is that after the type, I added square brackets. This is what tells the compiler we are creating an array of strings. You can define arrays with any of the native types, such as numbers or Boolean, or with your own custom types.

For-in Loop

The very first time I wanted to loop over an array, I used a for-in loop, like this:


let bodyString : string = "";
for (let person in personArray){
bodyString += echo(messageIntro + " " + person + "<br/>");
}
document.body.innerHTML = bodyString ;

I had used for-in loops in other languages, such as ActionScript so this was my natural impulse.

Let's look at the results:

Instead of outputting the data in the array, it outputted the index. The proper way to use a for-in loop in TypeScript would be like this:


for (let person in personArray){
bodyString += echo(messageIntro + " " + personArray[person] + "<br/>");
}

This isn't much different than a generic for loop that uses a counter, although the syntax is a bit nicer:

All version of ECMAScript after 2015 support for-in loops the same way that TypeScript does. This is supported by most browsers and in fact that generated JS Code uses for-in loops:


for (var person in personArray) {
bodyString += echo(messageIntro + " " + person + "<br/>");
}

But, this result wasn't quite what I was after. Thankfully TypeScript includes another option, the for-of loop.

For-Of Loops

A for-of loop makes one syntactical difference than a for-in loop. Instead of using the keyword in, it uses the keyword on:


for (let person of personArray){
bodyString += echo(messageIntro + " " + person + "<br/>");
}

This type of loop the loop counter, person, will match the value of the personArray instead of the index. After the compilation this is turned into a for loop with an explicit counter:


for (var _i = 0, personArray_1 = personArray; _i < personArray_1.length; _i++) {
var person = personArray_1[_i];
bodyString += echo(messageIntro + " " + person + "<br/>");
}

Compile this code and load it in the browser to see the expected results:

Looping in TypeScript is not much different than looping in other languages.

The next entry in this series will focus on creating classes.

Keep up to date by reading DotComIt's Monthly Technical Newsletter

String Enums in TypeScript - Part 4

I'm writing a longer series of articles about Typescript. This will be extra material to support my upcoming Angular 4 book. This is the fourth part of that series. Check out part 1, part 2, and Part 3. This article will focus on creating String based Enums.

What is an Enum?

Enums are a data type I have not come across in most other languages, but they are inspired by C#. An enum is a way to give friendly names to numerical or string values. They are like an array with indexes, but more specific. I can envision using something like this with a view stack style component and using an enum to handle which view is currently displayed. Or, I might use it with an event class instance to determine what type of event occurred. Or it could be used to determine what color style to apply to certain text.

Create a String based Enum

It is interesting that Enum's can be used to represent textual values too. Look at this:


enum MyColors {
Blue = "#0000FF",
Red = "#FF0000",
Green = "#00FF00",
};

The value of the color name represents the hex value of the actual color. I recently could have used something similar when dynamically applying colors to the header of a site based on which section the user was viewing. Get the individual colors, and output them:


let myColor1 :MyColors = MyColors.Blue;
let myColor2 :MyColors = MyColors.Red;
let myColor3 :MyColors = MyColors.Green;

console.log(myColor1);
console.log(myColor2);
console.log(myColor3);

You'll see something like this:

Enums are an interesting data type, caught somewhere between an array and a class.

Keep up to date by reading DotComIt's Monthly Technical Newsletter

Enums in TypeScript - Part 3

I'm writing a longer series of articles about Typescript. This will be extra material to support my upcoming Angular 4 book. This is the third part of that series. Check out part 1 and part 2. This article will focus on Enums, a TypeScript data type that does not exist in JavaScript.

What is an Enum?

Enums are a data type I have not come across in most other languages, but they are inspired by C#. An enum is a way to give friendly names to numerical values. They are like an array with indexes, but more specific. I can envision using something like this with a view stack style component and using an enum to handle which view is currently displayed. Or, I might use it with an event class instance to determine what type of event occurred. Or it could be used to determine what color style to apply to certain text.

Create a Number based Enum

I'm going to start by creating a simple sample with a number based enum:


enum MyNumbers {
First,
Second,
Third
}

The MyNumbers enum contains four values each one representing a number. Since enums are sort of like arrays, the First item is at the 0 index, the second item will have the value of 1, and so on. We can use MyNumbers like it was it's own variable type:


let myNum :MyNumbers = MyNumbers.First;

Output this value.


console.log(myNum);

What do you think you'll get? Since it is the value of MyNumbers.First and that is the first element of the zero-based index, you'll get number 0:

A benefit of enums is that we can control the number scheme:


enum MyNumbers {
First = 1,
Second,
Third
}

We specified the First item is equal to the number 1. Turn each element into a variable:


let myNum1 :MyNumbers = MyNumbers.First;
let myNum2 :MyNumbers = MyNumbers.Second;
let myNum3 :MyNumbers = MyNumbers.Third;

Then output them:


console.log(myNum1);
console.log(myNum2);
console.log(myNum3);

You'll see:

Now our text numbers match up with the actual text index. We can control the numbers even if they aren't in sequential order. Add a new entry to the MyNumbers enum:


enum MyNumbers {
First = 1,
Second,
Third,
Ten = 10,
}

This is number 10, skipping four through 9. Grab it as a variable and output it:


let myNum10 :MyNumbers = MyNumbers.Ten;
console.log(myNum10);

Combined with our other outputs, you'll see something like this:

Enums provide a lot of flexibility.

Enums can also be created to use a string based index, and we'll discuss that in the next article.

Keep up to date by reading DotComIt's Monthly Technical Newsletter

More Entries

All Content Copyright 2005, 2006, 2007, 2008, 2009 Jeffry Houser. May not be reused without permission
BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002.