Types in TypeScript

Working with TypeScript or any other coding language means basically working with data, and such data can represent different sorts of content. This is what we know as types, a noun used to represent the fact that such data can be a text string, an integer value, or an array of these value types, among others. This is nothing new to JavaScript, since we have always been working implicitly with types, but in a flexible manner. This means that any given variable could assume (or return in the case of functions) any type of value. Sometimes, this led to errors and exceptions in our code because of type collisions between what our code returned and what we expected it to return type-wise. While this flexibility can still be enforced by means of any type that we will see later on in this chapter, statically typing our variables gives us and our IDEs a good picture of what kind of data we are supposed to find on each instance of code. This becomes an invaluable way to help debug our applications at compile time before it's too late.

String

Probably one of the most widely used primitive types in our code will be the string type, where we populate a variable with a piece of text:

var brand: string = 'Chevrolet';

Check out the type assignation next to the variable name, which is separated by a colon symbol. This is how we annotate types in TypeScript, as we already saw in the previous chapter.

Back to the string type, we can use either single or double quotes, and it is same as ECMAScript6. We can define multiline text strings with support for text interpolation with placeholder variables by using the same type:

var brand: string = 'Chevrolet';
var message: string = `Today it's a happy day! 
  I just bought a new ${brand} car`;

Declaring our variables the ECMAScript 6 way

TypeScript, as a superset of ECMAScript 6, supports expressive declaration nouns such as let, which informs us that the variable is scoped to the nearest enclosing block (either a function for loop or any enclosing statement). On the other hand, const is an indicator that the values declared this way are meant to feature always the same type or value once populated. For the rest of this chapter, we will enforce the traditional var notation for declaring variables, but remember that

Number

Number is probably the other most widespread primitive data type along with string and boolean. The same as in JavaScript, number defines a floating point number. The number type also defines hexadecimal, decimal, binary, and octal literals:

var age: number = 7;
var height: number = 5.6;

Boolean

The boolean type defines data that can be True or False, representing the fulfillment of a condition:

var isZeroGreaterThanOne: boolean = false;

Array

Assigning wrong member types to arrays and handling exceptions that arise by that can be now easily avoided with the Array type, where we describe an array containing certain types only. The syntax just requires the postfix [] in the type annotation, as follows:

var brands: string[] = ['Chevrolet', 'Ford', 'General Motors'];
var childrenAges: number[] = [8, 5, 12, 3, 1];

If we try to add a new member to the childrenAges array with a type other than number, the runtime type checker will complain, making sure our typed members remain consistent and our code is error-free.

Dynamic typing with the any type

Sometimes, it is hard to infer the data type out of the information we have at some point, especially when we are porting legacy code to TypeScript or integrating loosely typed third-party libraries and modules. Don't worry, TypeScript supplies us with a convenient type for these cases. The any type is compatible with all the other existing types, so we can type any data value with it and assign any value to it later on. This great power comes with a great responsibility though. If we bypass the convenience of static type checking, we are opening the door to type errors when piping data through our modules, and it will be up to us to ensure type safety throughout our application:

var distance: any;

// Assigning different value types is perfectly fine
distance = '1000km';
distance = 1000;

// Allows us to seamlessly combine different types
var distances: any[] = ['1000km', 1000];

The null and undefined JavaScript literals require special mention. In a nutshell, they are typed under the any type. This makes it possible later on to assign these literals to any other variable, regardless its original type.

Enum

Enum is basically a set of unique numeric values that we can represent by assigning friendly names to each one of them. The use of enums goes beyond assigning an alias to a number. We can use them as a way to list, in a convenient and recognizable way, the different variations that a specific type can assume.

Enums are declared using the enum keyword, without var or any other variable declaration noun, and they begin numbering members starting at 0 unless explicit numeric values are assigned to them:

enum Brands { Chevrolet, Cadillac, Ford, Buick, Chrysler, Dodge };
var myCar: Brands = Brands.Cadillac;

Inspecting the value of myCar will return 1 (which is the index held by Cadillac in the enum). As we mentioned already, we can assign custom numeric values in the enum:

enum BrandsReduced { Tesla = 1, GMC, Jeep };
var myTruck: BrandsReduced = BrandsReduced.GMC;

Inspecting myTruck will yield 2, since the first enumerated value was set as 1 already. We can extend value assignation to all the enum members as long as such values are integers:

enum StackingIndex { 
  None = 0,
  Dropdown = 1000,
  Overlay = 2000,
  Modal = 3000 
};
var mySelectBoxStacking: StackingIndex = LayerStackingIndex.Dropdown;

One last trick worth mentioning is the possibility to look up the enum member mapped to a given numeric value:

enum Brands { Chevrolet, Cadillac, Ford, Buick, Chrysler, Dodge };
var myCarBrandName: string = Brands[1];

Void

The void type definitely represents the absence of any type and its use is constrained to annotating functions that do not return an actual value. Therefore, there is no return type either. We already had the chance to see this with an actual example in the previous chapter:

resetPomodoro(): void {
  this.minutes = 24;
  this.seconds = 59;
}

Type inference

Typing our data is optional since TypeScript is smart enough to infer the data type of our variables and function return values out of context with a certain level of accuracy. When no type inference is possible, TypeScript will assign the dynamic any type to the loosely typed data at the cost of reducing type checking to a bare minimum.

However, it is always a good practice to ensure that the information we handle is conveniently described by explicitly annotating its type, so we can harness the benefit of having the compiler verifying correctness throughout our code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset