Playing With Objects

Playing With Objects

A Typescript Approach

Cover photo credit: An Article by Hassan Fatthy

Introduction

Typescript(TS) is definitely 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 TS 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 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. (submitResumeError.png)[] 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 an a boolean in the form of an object.

Oddish

There are some behaviors in TS which 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 contains an extra field rateIdea:9.4 and is passed on to createStartup

  • However this does not trigger static checking which is odd, considering the fact that we specified for only one parameter.

To avoid errors like this, we use Type Aliases.

Type Aliases

In the section prior to this, we tried to use a 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 function.

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 aliases:

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 choice 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

In wrapping up our exploration of TypeScript’s handling of objects, it’s clear that while TypeScript offers powerful tools for enhancing JavaScript’s type safety, it also comes with its quirks.

We’ve seen how TypeScript's static checking can sometimes be bypassed with certain object structures and how type aliases can help maintain stricter control over the types in our code.

By leveraging type aliases, you not only enforce consistent type definitions across your functions but also streamline your codebase, reducing redundancy and minimizing potential errors. This practice of using type aliases can be particularly valuable when dealing with complex data structures or multiple functions requiring similar type definitions.

In conclusion, mastering TypeScript’s type system, especially with the use of type aliases, can greatly enhance code reliability and readability. While TypeScript might not be a flawless solution, understanding its nuances and leveraging its features effectively can lead to more robust and maintainable code. So, as you continue to refine your TypeScript skills, keep these insights in mind to ensure your code is both efficient and error-resistant.