DEV Community

React GraphQL Academy
React GraphQL Academy

Posted on • Originally published at reactgraphql.academy on

A TypeScript tale - The almighty types

Table of contents:

“A type is a syntactic method for enforcing levels of abstraction in programs. The study of type systems, and of programming languages from a type-theoretic perspective, has important applications in software engineering, language design, high-performance compilers, and security.” Benjamin C. Pierce

Types are (almost) all that TypeScript cares about. And even if there are many guides out there with these definitions, I couldn’t imagine writing this ‘TypeScript Tale’ of mine without adding my two cents.

JavaScript distinguishes types between primitives and non-primitives and their fundamental difference is that primitives are immutable. All the others are objects. We won’t be digging into this topic for now but you can have a look at the MDN documentation.

Note: We shouldn’t use Number, String, Boolean, Symbol, or Object to define types in TypeScript. These types refer to non-primitive objects that 99.9% of the times, will not have the effect we are trying to get from number, string, boolean or symbol. For instance, the global object String (with capital S) is a constructor for strings or a sequence of characters. It’s different from string (with capital s), which refers to a variable that holds a literal string (anything in between single/double quotes).

Boolean

One of the types we first come across when learning JavaScript. It can be defined as true or false.

const foo: boolean = true

String

Another of the basic types and it’s a set of characters that can also contain spaces and numbers. It must start and end with quotes (double or single).

const foo: string = "bar"

Number

In some programming languages Numbers are divided into Floats, Integers, Doubles or Bignums. In TypeScript we only use number.

const foo: number = 36
const bar: number = 1.84

Null and Undefined

These are well-known types and often misunderstood. They mean different things:

  • null : something that is currently unavailable
  • undefined : something that hasn’t been initialized

By definition they are subtypes of the other types. This means they can be assigned to number or string, for instance. These types are not very useful in TypeScript. Especially if we turn the — strictNullChecks on. In this mode, null and undefined cannot be used unless assigned to themselves or the any type. I encourage this option to be used because it protects us from referencing nulls or undefined values in code.

const foo: undefined = undefined
const bar: null = null

Void

Void is the absence of type. It can be seen in functions that do not return a value, such as a console.log().

const foo = (): void => {
  console.log("Hello there")
}

Any

Times will come that we don’t know our variable type while writing code. The reasons might be that we are using a 3rd party library or an API that is not ready yet. The any type, when used, will act as a bypass and let us continue our work. However, what would it be the point of typing any if the whole purpose of TypeScript is to introduce static types in JavaScript? We all know there are times we need to ship fast or we are just frustrated but, in this case, the trade-off might be a run-time error. Shall we skip unit tests if they are important for our codebase?

let foo: any = 5
foo = "is it a string?"
foo = true; // it's true that I don't know so it's a boolean

Never

The never type represents the type of values that never occur. We usually use never in a function that throws an exception or that never returns. We can also apply never when using type guards that can never be true.

const error(message: string): never {
   throw new Error(message)
}
const infiniteLoop(): never {
   while (true) {
   }
}

Array

TypeScript makes use of arrays in the same way as JavaScript are used to store multiple values in a single variable. It can be used in two different ways. The first using brackets after the element type:

let foo: string[] = ['foo', 'bar', 'baz']

The second using a generic array type Array< elementType > :

let sports: Array<string> = ['foo', 'bar', 'baz']

Enum

Enum or enumerations are used in object-oriented languages like Java and C#. TypeScript allows us to use it too. In simple words, enum is a way of giving more friendly names to sets of values. There are three types:

  • Numeric enum
  • String enum
  • Heterogeneous enum
enum Color {Red, Green, Blue}
let c: Color = Color.Green;

By default, the members of an enum start with index 0. But we can change this by manually setting:

The initial value:

enum Color {Red = 1, Green, Blue}
let c: Color = Color.Green

Or individual values:

enum Color {Red = 1, Green = 6, Blue = 9}
let c: Color = Color.Green

The string enum would, obviously, use string instead of number:

enum Sports {
   Boxing = "BOXING",
   Football = "FOOTBALL",
   Volleyball = "VOLLEYBALL"
}

Sports.Boxing

The Heterogeneous enum would be a mix of strings and numbers:

enum Sports {
   Active = 'ACTIVE',
   howMany = 3
}

Tuple

The tuple will allow us to determine a fixed and heterogeneous collection of values, such as string and number in an array. This is especially useful if we want a representation of key-value pairs.

let foo: [string, number] = [“bar”, 36]

We can access it also with its index:

console.log(foo[0]); // "bar"

Object

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

With object type, APIs like Object.create can be better represented. For example:

declare function create(o: object | null): void;

create({ prop: 0 }) // OK
create(null) // OK

create(42) // Error
create("string") // Error
create(false) // Error
create(undefined) // Error

So far we’ve had a grasp of the types available to us. It might not look important but these are the building blocks of the TypeScript programming language. During the next episodes we’ll learn not only how to use them, but also how to mix and build powerful typed integrated systems.

Related articles

Previous:

A TypeScript Tale - Episode 1

A TypeScript tale - How to setup and configure

Next:

A TypeScript tale - Interfaces, Classes & Generics

Top comments (0)