TypeScript static members

TypeScript static members

In TypeScript we can use static properties and methods inside classes. This article details how to use them, and how they transform into ES3/ES5 JavaScript, so that our code can run in all the current and not so current browsers.

TypeScript is not the only way of using classes and static properties or methods in JavaScript. Actually, classes have become a part of the final ES6 specification. Writing plain JavaScript we can also use classes. But when using TypeScript we get the benefit of the optional typing.

About classes and inheritance

First, a word of caution: being able to use classes does not mean that we should always opt for using them. It is outside of the scope of this article, but, as a rule of thumb, when using classes and OOP, we should be careful and try to favour composition over inheritance.

TypeScript static properties and methods

Let’s dive into some code directly, and then we will review each part of it. It is a simple class with a public method, a static method and a static property. Also, the constructor increases the static property, which is a number.

class MyClassWithStaticMembers {
    static aStaticCounter: number = 0;
    aPublicNumber: number = 0;
    constructor() {
        console.log(MyClassWithStaticMembers.aStaticCounter++);
    }
    aPublicMethod() {
        console.log("This is a public method")
    }
    static aStaticMethod() {
        console.log("This is a static method")
    }
}

MyClassWithStaticMembers.aStaticMethod(); // This is a static method

let foo = new MyClassWithStaticMembers(); // 0
let bar = new MyClassWithStaticMembers(); // 1
foo.aPublicMethod() // This is a public method

foo.aStaticMethod() // Error
MyClassWithStaticMembers.aPublicMethod() // Error

We can see that it works much like we would expect. TypeScript static methods are accessed by using the class, as we can see with MyClassWithStaticMembers.aStaticMethod();. Static methods and properties are separated from the class instances, as we can see with the static counter increasing when we instantiate foo and bar.

Also note that we cannot access static members directly from the object instances, that is why foo.aStaticMethod() gives us an error. The classes have a static part and a non-static part.

The compiled JavaScript code

Let’s take a look at the resulting compiled JavaScript to understand what is going on.

var MyClassWithStaticMembers = (function () {
    function MyClassWithStaticMembers() {
        console.log(MyClassWithStaticMembers.aStaticCounter++);
    }
    MyClassWithStaticMembers.prototype.aPublicMethod = function () {
        console.log("This is a public method");
    };
    MyClassWithStaticMembers.aStaticMethod = function () {
        console.log("This is a static method");
    };
    MyClassWithStaticMembers.aStaticCounter = 0;
    return MyClassWithStaticMembers;
}());

As we can see, classes get changed into functions. Instance methods are set into the prototype, while static members are assigned to the constructor function. That is why we can access static methods anytime, but they are not accessible from an instance.

Conclusion

We can use TypeScript static properties and methods inside classes. The instance members and the static members are completely separated. The instance members belong to each instance, but the static members are shared accross.

Using non React components with React

Using non React components with React

Sometimes the cost of rewriting a UI component from scratch is no assumable in real-world projects. I am writing the front-end for a new application using React and Redux, but I find myself in the position of having to use components that are already tested and are not written with React in mind. How does React play with non-React components? Actually, quite well, but requires taking care of some points. The gist for the example is here.

React and the Virtual DOM

React biggest advantage is the use of a Virtual DOM. We write components in the Virtual DOM, and React updates the real DOM accordingly for us. When we update the Virtual DOM, React will calculate the differences with the previous state and render only the necessary changes to the real DOM. This makes interacting with the real DOM directly a problem, because if we don’t take care, we might break the sync between real and virtual DOMs. Luckily, React offers some methods in its Component API that make using non-React components quite easy.

Example: Using jQuery UI Slider with React

At work, even now we are slowly moving to React, we used jQuery UI a lot. We even created our own widgets using the jQuery UI Factory. That means that we have a lot of UI widgets that we want to continue using if possible, at least for now.

For our example, we will be using the Slider widget, and show the value of the slider using React. I will be using TypeScript, but the same principles are applicable to plain JavaScript or ES6.

Three React components

We will keep the project as simple as possible. We will create 3 components:

  • ReactSliderApp: The parent component, and the glue between our two child components
  • SliderValue: A pure React component, it only shows the slider value
  • JQueryUISlider: A React component that wraps and uses jQuery UI Slider widget

The gist can be found here.

Wrapping a non React component with React

Let’s take a closer look to the JQueryUISlider component:

class JQueryUISlider extends React.Component<JQueryUISliderProps, void> {
    componentDidMount() {
        const parent = ReactDOM.findDOMNode(this);
        const slider = $(parent).slider({
            min: 0,
            max: 100,
            value: this.props.value,
            change: (evt: Event, ui: any) => {
                this.props.onChange(ui.value);
            }
        });
    }
    componentWillUnmount() {
        const parent = ReactDOM.findDOMNode(this);
        $(parent).slider("destroy");
    }
    shouldComponentUpdate() {
        return false;
    }
    render() {
        return (
            <div></div>
        );
    }
}

There are 4 important steps that need to be taken care of when working with non React components in React.

First, the render() method creates the minimal barebones that our component needs. Normally just an element we can attach the UI component to. In our example, it is just a div element without any property.

Second, the componentDidMount() method. This method gets called after React has created the real DOM elements. It gets called only once in the lifetime of the component. Inside this method, we should set up the non React component. We can access the real DOM element by using the findDOMNode() method. If our element has a changing state, we should set up the event listeners and callbacks too, like we did with the slider’s change method.

Third, the componentWillUnmount() method. This method gets called before React is about to remove the real DOM elements. But since React does not know about our slider, we need to get rid of it. In the case of jQuery UI widgets, it is done by calling the destroy method.

Fourth, and probably the most important, the shouldComponentUpdate() method. This method allows us to override the default React behaviour of updating the component when the state changes. Because we are handling the changes to our element ourselves, we need to return false.

Conclusion

It is possible to use non React components when necessary, for example when migrating a legacy system to use React. There are thousands of non React JavaScript components that we can use, but we need to take care of handling their life cycle when using them with React.

Type checking in TypeScript

Type checking in TypeScript

Many times we want to do type checking and assertion, it is one of the base elements of OOP. This article details the ways of checking types in TypeScript. For example, how to check if an object is an instance of a certain class. Or if it implements methods of a certain interface.

In a previous article I explained what interfaces are and are not in TypeScript. Because interfaces are non-existent in JavaScript, there is no way of checking if an object implements a given interface. Well, that is true, but TypeScript offers some workarounds for it, and we will see that too. What about plain JavaScript? It is not true that JavaScript has no type checking. There are some ways of checking types in JavaScript that work in TypeScript too.

JavaScript native type checking in TypeScript

JavaScript offers  that returns the typeof the operand. The usage is simple, but the results are not so simple:

let a = "Hello";
let b = 5;
let c = new Date();
let d = function D() { return true; };
class E {};
let e = new E();

console.log(typeof a);  // string
console.log(typeof b);  // number
console.log(typeof c);  // object
console.log(typeof d);  // function
console.log(typeof e);  // object
console.log(typeof E);  // function

The results for a and b are simple: string and number. The others need a bit more of thought. The c returns an object type, and d returns function. The instantiated e is an object, but E itself is a function.

I recommend using typeof for checks of strings and numbers. For example, a function that takes as parameter a string or a number. If it is a string, we want to add some text. If it is a number, we want to add 1. See below, TypeScript understands the typeof operator and allows us to autocomplete and compile without errors.

function myFunction(value: string | number): string | number { 
    if (typeof value === "string") {
        return value.concat("this is a string so I can use concat"); // It is a string
    } else {
        return value + 1; // We know its a number 
    }
}

Checking an object instance type

But lets go back to our first example. What if we want to know, not the type itself, but if the object e is an instance of our E class? In this case we have the JavaScript instanceof operator. According to MDN, it “tests whether an object has in its prototype chain the prototype property of a constructor” with the syntax being object instanceof constructor. Means that it will check our object’s prototype chain to see if it contains the one of the given constructor. In practice:

class Fruit {}
class Vegetable {}

let apple = new Fruit();

console.log(apple instanceof Fruit); // true
console.log(apple instanceof Vegetable); // false

We see that we can check that our apple is an instance of Fruit, not Vegetable. But lets complicate it a bit more, as seen below:

abstract class Person {
    age: number;
    name: string;
}

class Developer extends Person {
    developSomethingAmazing() {}
}

Here we have a Developer class extending a Person class. Lets do some tests with it:

let john: Person = new Developer();
john.age; // OK
john.developSomethingAmazing(); // ERROR 

let peter: Developer = new Developer();
peter.age; // OK
peter.developSomethingAmazing(); //OK

We see that if we instantiate an object as a Person (john) instead that as a Developer (peter), the compiler does not allow us to use all the Developer methods. Instead, if we check for the instance type of john first:

if (john instanceof Developer) {
    john.developSomethingAmazing(); // OK
}

console.log(john instanceof Person); // true
console.log(john instanceof Developer); // true

Also, we can check for parent types too: john is Developer, and also Person.

Checking types for interfaces

So far it looks like we can do anything we want. But lets refactor our last example to use interfaces:

interface CanDevelop {
    developSomethingAmazing();
}

interface CanDrinkCoffee {
    drinkCoffee();
}

abstract class Person {
    age: number;
    name: string;
}

class Developer extends Person implements CanDevelop, CanDrinkCoffee {
    developSomethingAmazing() {}
    drinkCoffee() {}
}

let john: Person = new Developer();

console.log(john instanceof Person); // true
console.log(john instanceof Developer); // true
console.log(john instanceof CanDevelop); // ERROR
console.log(john instanceof CanDrinkCoffee); // ERROR
if (john.developSomethingAmazing()) { // ERROR
 
}

We cannot use instanceof for interfaces. But TypeScript offers something called User defined Type Guards. Using the is operator we can create a function that checks if the class is in fact our interface implementation. We can use any logic we want, but we should return true or false.

function canDevelop(arg: any): arg is CanDevelop {
    return arg.developSomethingAmazing !== undefined;
}

if (canDevelop(john)) {
    (john as any as CanDevelop).developSomethingAmazing();
}

This is only a simple example of user defined type guards. Unfortunately, it is not as easy to use as it is in other languages as it requires to assert to any before asserting to our interface.

Conclusion

We have seen that we can use JavaScript’s typeof and instanceof for type checking, as well as define our own type guards if required.