Skip to main content

Basic Types

Type Annotations

  • What: Like type declaration in Java.
  • How: Syntax as following:
variable: type;

ES/TS Primitive Types

boolean

let bool: boolean = true;

number

let num: number = 123;

string

let str: string = 'abc';

symbol

Starting with ECMAScript 2015, symbol is a primitive data type, just like number and string. symbol values are created by calling the Symbol constructor. In TypeScript, it supports these two ways to define the symbol variables:

let s1: symbol = Symbol(); // OK
let s2 = Symbol(); // OK

s2 = 1; // Error, Type '1' is not assignable to type 'symbol'.

Indeed, TS can infer the s2 type:

D3twOQ

undefined & null

In TypeScript, both undefined and null actually have their own types named undefined and null respectively. They’re not extremely useful on their own:

let und: undefined = undefined;
let nul: null = null;

und = 1; // Error, Type '1' is not assignable to type 'undefined'.
nul = 1; // Error, Type '1' is not assignable to type 'null'.

By default null and undefined are subtypes of all other types. That means you can assign null and undefined to something like number.

let num: number = 1;
num = undefined; // OK
num = null; // OK

However, when using the --strictNullChecks flag, null and undefined are only assignable to any and their respective types (the one exception being that undefined is also assignable to void). This helps avoid many common errors. In cases where you want to pass in either a number or null or undefined, you can use the union type number | null | undefined.

tip

We encourage the use of --strictNullChecks when possible.

But for the purposes of this handbook, we will assume it is turned off.

ES/TS Reference Types

object

object is a type that represents the non-primitive type, i.e. anything that is not number, string, boolean, bigint, symbol, null, or undefined.

let obj: object = {x: 1, y: 2}; // (I)
obj.x = 3; // Error, Property 'x' does not exist on type 'object'.

As we haven't define the specific types for obj, but why are there no errors in line (I)? It's so weird. At last, we can correct it by redefining the type like below:

let obj: {x: number; y: number} = {x: 1, y: 2};
obj.x = 3; // OK

But it's weird when we use it as following:

let obj: object = {x: 1, y: 2};
obj['x'] = 2; // OK if `--noImplicitAny` is not given

object vs. Object vs. {}

Perhaps confusingly, TypeScript defines several types that have a similar name but represent different concepts:

  • object
  • Object
  • {}

We've already looked at the new object type above. Let's now discuss what Object and {} represent.

The Object Type

TypeScript defines another type with almost the same name as the new object type, and that's the Object type. While object (lowercased) represents all non-primitive types, Object (uppercased) describes functionality that is common to all JavaScript objects. That includes the toString() and the hasOwnProperty() methods, for example.

Within the lib.es6.d.ts file shipping with TypeScript, the Object type is defined as follows:

interface Object {
// ...

/** Returns a string representation of an object. */
toString(): string;

/** Returns a date converted to a string using the current locale. */
toLocaleString(): string;

/** Returns the primitive value of the specified object. */
valueOf(): Object;

// ...
}

However, variables of type Object only allow you to assign any value (if --strictNullChecks is not given) to them. You can’t call arbitrary methods on them, even ones that actually exist:

let prettySure: Object = 4; // OK
prettySure.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object'.
tip

Avoid using Object in favor of the non-primitive object type, please use the non-primitive object type (added in TypeScript 2.2).

The Empty Type {}

There's yet another type which is quite similar: {}, the empty type. It describes an object that has no members on its own. TypeScript issues a compile-time error when you try to access arbitrary properties on such an object:

let obj = {}; // Type {}

obj.prop = 'value'; // Error, Property 'prop' does not exist on type '{}'.

However, you can still use all properties and methods defined on the Object type, which are implicitly available via JavaScript's prototype chain:

let obj = {}; // Type {}

obj.toString(); // "[object Object]"

Similar to Object, you can also assign any value (if --strictNullChecks is not given) to {} type, but please don't do that which will cause some potential issues.

Array

TypeScript, like JavaScript, allows you to work with arrays of values. Array types can be written in one of two ways.

1. elemType[]

In the first, you use the type of the elements followed by [] to denote an array of that element type:

let arr1: number[] = [1, 2, 3];

2. Array<elemType>

The second way uses a generic Array type which is predefined in typescript.

let arr2: Array<number> = [1, 2, 3];

But how should we do if we want to use different types in one array?

We can use union type to define the elements' types:

let arr3: Array<number | string> = [1, 2, 3, 'a'];

Function

See more at Function -> Types section.

TS Special Types

void

Similar to languages like Java, void is used where there is no data type. For example, in return type of functions that do not return any value:

function sayHi(): void {
console.log('Hi!');
}

let speech: void = sayHi();
console.log(speech); //Output: undefined

There is no meaning to assign void to a variable, as only null or undefined is assignable to void (only if --strictNullChecks is not specified):

let nothing: void = undefined;
nothing = null; // OK if `--strictNullChecks` is not given
let num: void = 1; // Error

any

TypeScript has type-checking and compile-time checks. However, we do not always have prior knowledge about the type of some variables, especially when there are user-entered values from third party libraries. In such cases, we need a provision that can deal with dynamic content. The any type comes in handy here.

let x; // Variable 'x' implicitly has an 'any' type, but a better type may be inferred from usage.
// or
let x: any;

x = 123;
x = 'abc';
x = {};
x = () => {};

Similarly, you can create an array of type any[] if you are not sure about the types of values that can contain this array.

let arr = [123, 'abc'];
// or
let arr: any[] = [123, 'abc'];

With the intent of compatibility of JS, any may be useful in some scenarios, but we should not count on it.

tip

We should use any as less as possible.

never

The never type is used when you are sure that something is never going to occur. For example, you write a function which will not return to its end point or always throws an exception.

function throwError(errorMsg: string): never {
throw new Error(errorMsg);
}

function endless(): never {
while (true) {
console.log('I always does something and never ends.');
}
}

never type is used to indicate the value that will never occur or return from a function.

Tuple

Tuple is a special type of array which allows you to express an array with a fixed number of elements whose types are known, but need not be the same.

typescript-tuple
let tuple1: [number, string] = [1, 'a']; // OK

// Order Change
let tuple2: [number, string] = ['a', 1]; // Error

// Element Type Change
let tuple3: [number, string] = ['a', 'b']; // Error

// Add New Element
let tuple4: [number, string] = [1, 'a', 'b']; // Error

// Same Types
let tuple5: [number, number] = [1, 1]; // OK, but use `number[]` will be better

In addition, we cannot cross its boundary to access the element:

tuple1[2]; // Error, Tuple type '[number, string]' of length '2' has no element at index '2'.

As we all know we can't add new element in tuple by literal, but it looks a bit weird when use push():

tuple1.push(2); // OK
console.log(tuple1); // [1, 'a', 2]
tuple1[2]; // Error, Tuple type '[number, string]' of length '2' has no element at index '2'.
caution

Use push() method in tuple is a bad idea.

In the following scenario, you should pay more attention on the middle variable:

let aa = [1, 'a'];
let tuple: [number, string] = aa; // Type '(string | number)[]' is missing the following properties from type '[number, string]': 0, 1

TS will infer the type of aa as following shows:

CnKoW1

We can correct this error via removing middle variable aa or redefining the type of aa:

let aa: [number, string] = [1, 'a'];
let tuple: [number, string] = aa; // OK

References

  1. TypeScript Data Type - Tutorials Teacher
  2. TypeScript official docs: Basic Types
  3. TypeScript official docs: Do's and Don'ts
  4. TypeScript in action, By Liang Xiao
  5. The object Type in TypeScript, By Marius Schulz