TypeScript Basics IV: Enums, Object Types, and Type Aliases

James Ng
5 min readNov 30, 2022
TypeScript logo

TypeScript allows for custom types, which will allow for greater flexibility to be strict (…sounds ironic 🤔) when writing code. These include enums, object types, type aliases, function types, generic types, and generic functions. This writing will only cover enums, object types, and type aliases and the next post will cover function and generic types.

Numeric Enums

The complex type enums allows us to enumerate all possible values assigned to a variable. For example, the planets of our solar system can be defined as

enum Planets { Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune };

Technically, we can use an array type string[] or tuple type [string, string, …, string] to achieve the same results, but they can be literally anything and therefore be error-prone if we are not careful. For example,

let PlanetsArrayType: string[];
let PlanetsTupleType: [
string, string, string, string,
string, string, string, string
];
PlanetsArrayType = [
'Mercury', 'Venus', 'Earth', 'Mars',
'Jupiter', 'Saturn', 'Uranus', "🥾 Neptune - PLUTO!"
] // or PlanetsTupleType
let planetToExplore = Planets;
planetToExplore = Planets.Neptune; // No type error.
planetToExplore = Earth; // Error, incorrect syntax. Use Planets.Earth.
planetToExplore = Planets.Pluto; /* Error, Pluto is not a valid value
for Planets enums */

By default, all the values in enum Planets are 0-indexed in the order they appear. In other words,Planets.Mercury = 0 , Planets.Venus = 1 , Planets.Earth = 3 , and so on. Different numbers can be assigned to each value like such:

enum Planets {
Mercury=5, Venus=3, Earth=1, Mars=4,
Jupiter=8, Saturn=7, Uranus=2, Neptune=6
}
let planetToExplore: Planets; //assigns enum Planets to variable
planetToExplore = Planets.Mars// No error
planetToExplore = 4 // No error, same as above
planetToExplore = 1234 // No error but strange....

Additionally, a non-zero starting index can be assigned to the first value and TypeScript assigns the rest of the indices incrementally by 1.

enum Planets {
Mercury=1, Venus, Earth, Mars,
Jupiter, Saturn, Uranus, Neptune
}
Planets.Mercury === 1 //true
Planets.Earth === 3 //true
Planets.Neptune === 7 //false

Some practical applications of numeric enums are keeping track of a favorites count or an inventory count for stores. This allows for us to just use the item’s index as opposed to typing out each item.

String Enums

As we saw in the example above with where the variable planetToExplore can be assigned to any number, such as planetToExplore = 1234, and can lead to bugs and errors. That might be a little too flexible for the strict reputation of TypeScript. String enums are generally used in lieu of numeric enums because variables cannot be assigned to arbitrary numbers or strings at all!

// Numeric Enum
enum PlanetsNum { Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune }
// String Enum
enum PlanetsStr {
Mercury = 'MERCURY', Venus = 'VENUS', Earth = 'EARTH', Mars = 'MARS',
Jupiter = 'JUPITER', Saturn = 'SATURN', Uranus = 'URANUS', Neptune = 'NEPTUNE'
}

Although it seems counterintuitive, string nums do not allow us to assign variables with the string values we defined above. The only valid syntax is the object-key syntax Object.key .

Object Types

Object types are the most common of the custom types. They allow for greater control of variable types and data input. Type annotations for objects look like object literals.

let dog: { name: string, age: number, breed: string, vaccinated: boolean };

When dog is assigned as an object, it must have the name , age, breed, and vaccinated properties of the specific types or else TypeScript will throw errors.

In the example above line 5, the variable dog was assigned values to all properties except for vaccinated, resulting in an error.

There are no restrictions on assigning types for the object’s properties. For example, the variable myProfile can be assigned the following:

let myProfile: {
age: number,
color: string,
favFoods: string[],
friends: { name: string, phone: number }[],
favSuperHero: { name: string, powers: [string, string] },
voted: boolean,
graduated: boolean
}

Type Aliases

TypeScript allows for type aliases, or arbitrary names that we can choose to assign to types for further customization in our programs. The format is type <alias> = <type> .

We can refactor the variable myProfile defined earlier by using type aliases like such:

type Person = { name: string, phone: number };
type SuperHero = { name: string, powers: [string, string] };

let myProfile: {
age: number,
color: string,
favFoods: string[],
friends: Person[],
favSuperHero: SuperHero,
voted: boolean,
graduated: boolean
}

Furthermore, we can assign the type alias Profile to define the all the properities in myProfile like such:

type Person = { name: string, phone: number };
type SuperHero = { name: string, powers: [string, string] };
type Profile = {
age: number,
color: string,
favFoods: string[],
friends: Person[],
favSuperHero: SuperHero,
voted: boolean,
graduated: boolean
}

let myProfile: Profile = {
age: 23, color: 'Blue', favFoods: ['pizza', 'peanut butter'],
friends: [
{ name: 'David', phone: 8001234567 },
{ name: 'Christina', phone: 8887654321 }
],
favSuperHero: { name: 'Superman', powers: ['flying', 'laser'] },
voted: true,
graduated: true
}

Refactoring with type alias makes our code readable and reusable.

Summary

  • Custom types allow for flexibility in TypeScript. Numeric enums assign indices to all possible values assigned to a variable. String enums are stricter in that the proper syntax — Object.key — must be used.
  • Object types are most common and take on the form of an object literal. There are no restrictions on assigning types for the properties of the object.
  • Type alias are arbitrary names that can be used to further customize our programs, making code more readable and reusable.

Credit & Inspiration: Codecademy’s Learn TypeScript course

--

--

James Ng

Software engineer, math & physics educator, mentor