Using TypeScript — Arrays. Empty arrays, type inference and more.
By: John Au-Yeung
Tags: Technology, Software Development, JavaScript, Programming, Web Development

Photo by Dan Gold on Unsplash

TypeScript is a natural extension of JavaScript that’s used in many projects in place of JavaScript.

However, not everyone knows how it actually works.

In this article, we’ll look at how to define and use arrays in our TypeScript code.

Working with Arrays

JavaScript arrays can contain data from any combination of types and have variable lengths.

Items can be added or removed without the needed to resize the array explicitly.

TypeScript doesn’t change the flexible array sizing, but we can use it to restrict the types of data that can be in an array.

For instance, we can write:

let prices: number[] = [48, 23, 41];

to restrict the prices array to only hold numbers.

number is the data type of each entry and [] indicates that it’s an array.

We can also use parentheses to indicate that an array can hold entries with different types of data.

For instance, we can write:

let prices: (number | string)[] = [48, 23, '88'];

So that prices can have strings in addition to numbers.

TypeScript will ensure that only operations that are allowed for number values are performed by the function.

Equivalent Array Syntax

We can specify the array data type with brackets.

For instance, we can write:

let prices: Array<number> = [48, 23, 88];

which is the same as:

let prices: number[] = [48, 23, 88];

Inferred Typing for Arrays

If the data type is obvious from the values, then we don’t have to write the data type annotation explicitly.

For instance, we can write:

let prices = [48, 23, 88];

The TypeScript compiler will know that we have a number array just from the assignment.

We can see that if we loop through the array with forEach and try to do something with each entry:

let prices: number[] = [48, 23, 88]; prices.forEach(p => {

console.log(p.toFixed(2));

});

The compiler lets us call the toFixed method on an array, which is a method available for numbers.

It’s great at inferring type from existing values.

Problems with Inferred Array Types

We may run into problems if we have a possibility of type mismatches.

For instance, we can write:

const prices: number[] = [48, 23, 88];

const taxes: number[] = []; const getTax = (price: number, format: boolean) => {

if (format) {

return (price * 0.2).toFixed(2);

}

return price * 0.2;

}; prices.forEach(p => {

taxes.push(getTax(p, false));

});

We’ll get the error:

Argument of type 'string | number' is not assignable to parameter of type 'number'. Type 'string' is not assignable to type 'number'.ts(2345)

from the compiler since getTax may return a number or a string.

Even if we pass in false , which should return a number, the compiler isn’t smart enough to figure that out on its own.

Therefore, we can either set the type of taxes to be number | string .

Or we can assert that each entry is a number.

Empty Arrays

If we have an empty array, the type would be inferred as any[] implicitly.

To avoid this, we should specify the type of it explicitly.

This applies if strictNullChecks is set to false .

never Array Type

When null and undefined aren’t assignable to other types, Typescript infers to empty arrays differently.

It’ll have the never type instead of any[] if strictNullChecks is set to true .

Inferring the type as never ensures that the array doesn’t escape any type checking process and the code won’t compile until the type of each entry is asserted or the array is initialized to the values that let the compiler infer the type.

Conclusion

TypeScript can infer the types of arrays if entries are added explicitly.

Inferred array types are different for empty arrays depending if strictNullChecks is true or not in the compiler options.

We can also set the type of arrays explicitly.

The TypeScript compiler isn’t smart enough to infer all data types on its own.

So data type assertions may be needed.