Understanding Primitive Types, Type Annotations and Non-Primitive Types in TypeScript

TypeScript 101 Series - Episode 2

Understanding Primitive Types, Type Annotations and Non-Primitive Types in TypeScript

⭐ Intro

Welcome to the second episode of the TypeScript 101 series! In this blog post, we'll delve into the fundamental concepts of primitive types, type annotations, and non-primitive types in TypeScript. Understanding these concepts is crucial for writing type-safe, readable, and maintainable code.

⭐ Primitive Types

TypeScript has three very commonly used primitives: string, number, and boolean.

🪢 String

The string represents string-like values.

Example:

const name: string = "Sridhar Maskeri";

🔢 Number

The number represents number-like values. TypeScript does not have a special runtime value for integers, so there’s no equivalent to int or float - everything is simply number .

All the numbers in TypeScript are stored as floating-point values.

TypeScript also supports Binary(Base 2), Octal(Base 8), Decimal(Base 10) and Hexadecimal(Base 16) literals.

let first: number = 12.0;             // number   
let second: number = 0x37CF;          // hexadecimal  
let third: number = 0o377 ;           // octal  
let fourth: number = 0b111001;        // binary   

console.log(first);           // 123  
console.log(second);          // 14287  
console.log(third);           // 255  
console.log(fourth);          // 57

☯️ Boolean

The boolean type denotes the two boolean values true and false.

Example:

const isValid: boolean = true;

⚠️ Disclaimer

The type names String, Number, and Boolean (starting with capital letters) are legal, but refer to some special built-in types that will very rarely appear in your code. Always use string, number, or boolean for types.

⭐ Type Annotations on Variables

When you declare a variable using const, var, or let, you can optionally add a type annotation to explicitly specify the type of the variable (like we did in the above examples).

let name: string = "Sridhar Maskeri";

In most cases, though, this isn’t needed. Wherever possible, TypeScript tries to automatically infer the types in your code. For example, the type of a variable is inferred based on the type of its initializer:

// No type annotation needed -- 'name' inferred as type 'string'
let name = "Sridhar Maskeri";

For the most part you don’t need to explicitly learn the rules of inference. If you’re starting out, try using fewer type annotations than you think - you might be surprised how few you need for TypeScript to fully understand what’s going on.

⭐ Non-Primitive Types

The non-primitive types are: array, tuples, Function, any , object.

👪 Array

The array type in TypeScript allows you to define a collection of values of the same type. Arrays are declared using square brackets []. You can specify the type of elements within the array by using the syntax type[] or Array<type>.

Example:

// Declaring an array of numbers and strings
let numbers: number[] = [1, 2, 3, 4, 5];
let fruits: string[] = ["apple", "banana", "orange"]

// Another way of decalring arrays using Generic
let numbers: Array<number> = [1, 2, 3, 4, 5];
let fruits: Array<string> = ["apple", "banana", "orange"];

🧑‍🤝‍🧑 Tuples

Tuples are TypeScript types that allow you to express an array with a fixed number of elements, where each element may have a different type. Tuples are declared by specifying the types of each element within square brackets [].

Example:

// Declaring a tuple with two elements: string and number
let person: [string, number] = ["John Doe", 30];

// Accessing tuple elements
console.log(person[0]); // Output: John Doe
console.log(person[1]); // Output: 30

🤖 Function

The Function type represents a JavaScript function. Functions can have parameters and return values. In TypeScript, you can define the types of the function's parameters and return value.

Example:

// Declaring a function with parameters and return type
function addNumbers(a: number, b: number): number {
  return a + b;
}

// Calling the function
let result: number = addNumbers(5, 10);
console.log(result); // Output: 15

In the above example, the addNumbers function takes two parameters of type number and returns a value of type number. By providing these type annotations, TypeScript ensures that the function is called with the correct argument types and that the return value is of the expected type.

😶‍🌫️ Any

The any type in TypeScript allows you to opt out of type checking for a particular value. When a variable is assigned the any type, it can hold values of any type.

Example:

let data: any = 10; // data can hold any type of value
console.log(data); // Output: 10

data = "Hello, TypeScript!";
console.log(data); // Output: Hello, TypeScript!

⚠️ Disclaimer

Using the any type in TypeScript is generally discouraged because it bypasses type checking, which is one of the main advantages of using TypeScript.

🎓 Object

The object type represents a non-primitive value in TypeScript, which can be any value other than number, string, boolean, symbol, null, or undefined. It is a type that encompasses all JavaScript objects.

Example:

let user: object = {
  name: "John Doe",
  age: 30,
  isAdmin: true
};

console.log(user.name); // Output: John Doe
console.log(user.age); // Output: 30
console.log(user.isAdmin); // Output: true

⭐ Summary

we explored the concept of primitive types, type annotations, and non-primitive types in TypeScript. We started by discussing the three commonly used primitive types: string, number, and boolean. We saw how to declare variables with type annotations and learned that TypeScript can often infer types automatically, reducing the need for explicit annotations.

Moving on to non-primitive types, we covered the array type, which allows you to define collections of values of the same type. We also introduced tuples, which represent fixed-length arrays where each element can have a different type. The Function type allowed us to define functions with specific parameter and return types.

We then touched upon the any type, which should be used sparingly as it bypasses type checking, reducing the benefits of TypeScript's type system. Finally, we discussed the object type, which represents non-primitive values and encompasses all JavaScript objects.

Stay tuned for more posts in my TypeScript 101 series, where we will explore further concepts and techniques to help you become a more proficient TypeScript developer.

Till then Happy Coding! 😉