Learn TypeScript: Primitive Data Types, Type Aliases, and Interfaces

You may want to read this article in Bahasa Indonesia version: Mengenal TypeScript: Tipe Data Primitif, Type Alias, dan Interface
Introduction
TypeScript has become the first choice for many JavaScript developers because it offers static typing and advanced features that help develop more robust and maintainable applications. In this article, we will discuss the basic concepts of TypeScript that are important for every developer to understand.
Data Types in TypeScript
TypeScript extends JavaScript by adding a static type system. Let’s discuss the most commonly used data types.
Primitive Data Types
TypeScript supports the same primitive data types as JavaScript, but with the ability to explicitly assign types. There are generally 3 most commonly used data types: string, number, and boolean.
/**
* string: for text values.
*/
let name: string = "Budi Santoso";
/**
* number: for numeric values (integer and floating point).
*/
let age: number = 25;
let height: number = 175.5;
/**
* boolean: for true/false values.
*/
let isMarried: boolean = false;
By explicitly specifying primitive types, TypeScript will warn us if we try to specify an inappropriate value:
let myName: string = "Budi";
myName = 123;
console.log("my name: ", myName);

Non-Primitive Data Types
Arrays
Arrays in TypeScript can be declared in two ways:
/**
* Way 1: using type[].
*/
let fruits: string[] = ["Apple", "Orange", "Mango"];
/**
* Way 2: using generic Array<type>.
*/
let numbers: Array<number> = [1, 2, 3, 4, 5];
/**
* Multidimensional array.
*/
let matrix: number[][] = [
[1, 2, 3],
[4, 5, 6],
];
Object
Objects in TypeScript can be defined by specifying their property types:
/**
* Define object with inline type.
*/
const person: { name: string; age: number } = {
name: "Andi",
age: 30,
};
/**
* Accessing properties.
*/
console.log(person.name); // "Andi"
Tuple
A tuple is an array type with a fixed number of elements and a predefined type for each position:
/**
* Define tuple.
*/
const coordinates: [number, number] = [10.5, 20.3];
/**
* Tuple with different types.
*/
let user: [string, number, boolean] = ["admin", 1, true];
/**
* Error: type mismatch.
*/
user = [1, "admin", true];
By using a tuple and explicitly specifying the type at each position, TypeScript will warn us if we try to specify an inappropriate value:

Type Alias
Type Alias allows us to create new names for data types. This is especially useful for complex types that will be used repeatedly:
/**
* Define simple type alias.
*/
type Name = string;
const myName: Name = "Dewi";
/**
* Type alias for object.
*/
type Person = {
name: string;
age: number;
/** optional property with ? */
address?: string;
};
/**
* Using type alias.
*/
const employee: Person = {
name: "Rudi",
age: 28,
};
/**
* Type alias untuk union type.
*/
type ID = string | number;
/**
* Valid because ID can be string or number.
*/
let userId: ID = 123;
userId = "ABC123";
Type Alias can also be used for more complex types such as function signatures:
/**
* Define function signature type alias.
*/
type Operation = (a: number, b: number) => number;
/**
* Implement function.
*/
const add: Operation = (a, b) => a + b;
const subtract: Operation = (a, b) => a - b;
console.log(add(5, 3)); // 8
console.log(subtract(5, 3)); // 2
Interface
Interfaces are another way to define a form of object in TypeScript. Interfaces are often used for contracts in object-oriented programming:
/**
* Define interface.
*/
interface Vehicle {
brand: string;
year: number;
drive(): void;
}
/**
* Implement interface.
*/
class Car implements Vehicle {
brand: string;
year: number;
constructor(brand: string, year: number) {
this.brand = brand;
this.year = year;
}
drive() {
console.log(`Car ${this.brand} is driving...`);
}
}
/**
* Using class that implements interface.
*/
const myCar = new Car("Toyota", 2020);
myCar.drive(); // "Car Toyota is driving..."
They also support inheritance:
/**
* Define interface.
*/
interface Animal {
name: string;
eat(): void;
}
/**
* Define interface that extends another interface.
*/
interface Carnivore extends Animal {
hunt(): void;
}
/**
* Implement interface with inheritance.
*/
class Lion implements Carnivore {
name: string;
constructor(name: string) {
this.name = name;
}
eat() {
console.log(`${this.name} is eating...`);
}
hunt() {
console.log(`${this.name} is hunting...`);
}
}
/**
* Using class that implements interface.
*/
const lion = new Lion("Lion");
lion.eat(); // "Lion is eating..."
lion.hunt(); // "Lion is hunting..."
Differences between Type Alias and Interface
Type Alias and Interface have many similarities, but also some important differences:
Extensions
Interface can be extended with extends
, while Type Alias uses the intersection(&
) operator.
interface AnimalInterface {
name: string;
}
/**
* Interface extension.
*/
interface CatInterface extends AnimalInterface {
meow(): void;
}
type AnimalType = {
name: string;
};
/**
* Type alias intersection.
*/
type CatType = AnimalType & {
meow(): void;
};
Merging Declarations
Interface with the same name will be automatically merged (declaration merging), while Type Alias will not.
/**
* Interface declaration merging.
*/
interface Person {
name: string;
}
interface Person {
age: number;
}
/**
* Result: interface Person { name: string; age: number; }.
*/
class Child implements Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
const child = new Child("John", 10);
/**
* Type alias cannot be declared twice.
*/
type Employee = {
name: string;
};
/**
* Error: Duplicate identifier 'Employee'.
*/
type Employee = {
age: number;
};

When to Use Type Alias or Interface?
As a general guide:
- Use Interface when:
- You are defining a form of object that will be implemented by a class.
- You want to utilize the declaration merging feature.
- You are working with the OOP (Object-Oriented Programming) pattern.
- Use Type Alias when:
- You are defining a primitive type, union, or tuple.
- You need to use mapped types or conditional types.
- You are working with the FP (Functional Programming) pattern.
A more complete review of the differences between Type and Interface can be read here: Learn TypeScript: Interface & Type
Conclusion
Understanding data types, type aliases, and interfaces is an important foundation in developing applications with TypeScript. By using these features appropriately, you can improve type safety, code readability, and reduce potential bugs in your application.