Mastering the Art of Objects

Mastering the Art of Objects

A TypeScript Journey

Cover photo credit: ceos3c.com

Introduction

Typescript (TS) is good but is not entirely the elixir to Javascript(JS) perfection. There are still some odd behaviors in TS, especially when dealing with objects. Sit tight as I unravel Typescript's behavior when it comes to objects.

Objects In TS

Objects are data structures primarily used for capturing key-value pairs. For instance, if you want to send an instance to a database, you can group the data in fields using a key : "name", and the values: "Kelvin", "Okuroemi". Here's one:

const infoAboutMe ={
    name: "Kelvin",
    age: 21,
    hasJob: false,
    hireMe: true
}

Most times, the reason TS is used when working with objects is to specify the data type of the inputs of object fields as they are used in a function:

function submitResume({name:string, hasJob: boolean}){
// Some code ...
}

As a result, calling the submitResume() function without an object parameter will trigger static checking.

To stop this, we have to specify the parameters,

submitResume({name: "Kelvin", hasJob: false})

Now if you wanted to specify that an object should have to return an object, you could do it by:

function submitResume({name:string, hasJob: boolean}):{isQualified: boolean}{
// Some code ...
return {isQualified:true}
}
  • Notice the output declaration syntax :{isQualified:boolean} that warrants the submitResume function to return a boolean in the form of an object.

Oddish

Some behaviors in TS might be able to evade TS static checking, for example:

function createStartup({name:string}){
//  Some code...
}
let details = {name:"SideSchool", rateIdea: 9.4}
createStartup(details)
  • createStartup function specifies only a name:string parameter.

  • details contain an extra field rateIdea:9.4 and is passed on to createStartup

  • However, this does not trigger static checking which is odd, because we specified only one parameter.

To avoid errors like this, we use Type Aliases.

Type Aliases

In the section before this, we tried to use variable details to specify a range of values, and it bypassed our TS static checking character. If we want to specify a range of types and still keep static checking in place, we use type aliases.

Type aliases help us specify a range of types to be used beforehand, and will flag errors if further components neglect the alias. Using our createStartup function from above:

type Startup = {
  name: string;
  niche: string;
  rateIdea: number;
};

function createStartup(startup: Startup): Startup {
  //  Some code...
  return name: {"SideSchool",niche:"EdTech", rateIdea: 9.4};
}

createStartup({ name: "SideSchool", niche: "EdTech", rateIdea: 9.4 });
  • First of all, we create a type alias Startup with the keyword type

  • Then we write that the createStartup function's parameter should have all the types already specified in the Startup type alias. It should also return a value with Startup type aliases.

  • After that, you call the function with the appropriate parameters and corresponding types as specified in the Startup type alias.

  • In this case, type aliases replace the use of the variable details for specifying a range of types and will trigger static checking if need be.

Another reason we might use the type aliases is to prevent scenarios where we have to define the same range of types for different functions.

No alias

function createStartup1({ name: string, cost: number }) {
  //  Some code...
}

function createStartup2({ name: string, cost: number }) {
  //  Some code...
}

function createStartup3({ name: string, cost: number }) {
  //  Some code...
}

With alisases

type StartupDetails = {
    name: string,
    cost: number
}

function createStartup1(details: StartupDetails) {
  //  Some code...
}

function createStartup2(details: StartupDetails) {
  //  Some code...
}

function createStartup3(details: StartupDetails) {
  //  Some code...
}

To cap it, we can also define type aliases to accommodate unions(a choice between two or more types).

type Union = string | number | boolean;

const unionVar0: Union = "union";
const unionVar1: Union = 46;
const unionVar2: Union = false;
  • We specify a Union type alias with three choices of types.

  • Then define all variables to have the type of Union, this can allow any variable to have any type already specified in Union type alias without triggering static checking.

Conclusion

TypeScript brings significant benefits to JavaScript development, but there are peculiar behaviors when it comes to dealing with objects.

One crucial aspect is the use of object types in TypeScript. By explicitly specifying the data type of object fields, we can achieve static checking and catch potential errors during compilation. This helps us validate the input parameters of functions and improve code robustness.

However, there are instances where TypeScript's static checking may not be triggered as expected, allowing some unexpected behaviors to slip through. To address this, we can leverage Type Aliases. Type Aliases allow us to define custom types, specifying a range of expected properties. By using Type Aliases, we ensure that TypeScript enforces static checking, preventing accidental misuse of object structures.

Additionally, Type Aliases prove valuable when multiple functions require the same range of types. By defining a common Type Alias, we avoid redundant type definitions and promote code reusability and consistency.

Furthermore, Type Aliases can accommodate unions, providing flexibility in choosing between multiple types for a variable. This enables us to handle scenarios where a variable can hold values of different types without compromising static checking.

By mastering TypeScript's object behavior and effectively utilizing Type Aliases, we can enhance our development workflow, reduce bugs, and improve the overall quality and maintainability of our TypeScript projects.