7 Common Errors And Possible Fix Every Typescript Developers Should Know.

stanlisberg

Stanlisberg

Posted on May 17, 2023

7 Common Errors And Possible Fix Every Typescript Developers Should Know.

Table of content

  1. Introduction
  2. What is typescript
  3. Type Error
  4. Syntax Error
  5. Configuration Error
  6. Null Error
  7. Missing Property Error
  8. Type Assertion Error
  9. Naming Convention Error

Introduction

A few months back, I completed a project and I had to utilize Typescript because it's one of the project requirements, and I must admit, TypeScript proved to be one of the most frustrating tools that I have encountered in my programming journey. “Are all these errors necessary?” This is a question I often ask myself each time I see that infamous red line highlighting my codes with error.

Coming from a JavaScript background, a dynamically typed programming language that affords us the liberty to declare variables and assign them any data type, I would say it was more of a herculean task working with typescript. I depended on many online resources like Google search, blog posts, StackOverflow, and thorough examination of the official documentation to scale through this hurdle which sometimes aggravates my confusion as everything seems overwhelming. Yes, TypeScript can be that daunting. I wouldn't say I am a typescript expert now, but I have actually improved significantly in my typescript knowledge since my previous engagement on that project.

In this article, I have curated a collection of some common errors I encountered during my early explorations of TypeScript and their corresponding solutions aiming to assist those who encounter similar challenges in their own code. Before we delve further, let's familiarize ourselves with the fundamentals of TypeScript. Shall we?

What is Typescript?

TypeScript is an open-source high-level programming language developed by Microsoft that adds strict typing with optional type annotation to JavaScript. It is a superset of JavaScript that transforms its code into raw JavaScript code, making it run smoothly in any JavaScript runtime environment.

Below are a few of the errors I encountered. They are:

Type Error

The Type error occurs when there is a variable type mismatch leading to some type-related inconsistencies in your code.

Error Code

let firstName: string = "Felix";
firstName = true; // Type error: Type 'boolean' is not assignable to type ‘string’
Enter fullscreen mode Exit fullscreen mode

In the code above, we declared a variable firstName with the type of string but got an error when we tried to assign the boolean value true to firstName.

Fixed Code

let firstName: string = "Felix";
firstName = 'Joshua';   // No error detected 
Enter fullscreen mode Exit fullscreen mode

Analyzing the code snippet above, we have assigned a valid string value of Joshua to firstName which has satisfied the expected type, thus leading to a type-safe code and resolved error.

Note: It is essential to carefully review our codes for possible misinterpretation of assigned value to a wrong type declaration to prevent type-related errors and help enhance code quality.

Syntax Error

The Syntax Error is identified when the TypeScript compiler responsible for compiling codes detects a syntactically invalid representation of the code while interpreting it.

Error Code

const userName = (name: string) => {
  console.log (`Hey! ${name}`)
}
userName("Frank); // Syntax Error: Unterminated string literal
Enter fullscreen mode Exit fullscreen mode

We declared an arrow function that accepts a parameter of name with type of string and at the bottom we called the function and passed an argument of a string Frank but forgot to add the second double quote, hence prompting the error.

Fixed Code

const userName = (name: string) => {
  console.log (`Hey! ${name}`)
}
userName("Frank"); // No error detected
Enter fullscreen mode Exit fullscreen mode

From the fixed code above, we have included the closing double quotes and gotten rid of the error message.

Note: We should develop a practice to consistently review our codes for potential syntax mistakes like wrong placement of semicolons, quotes, parenthesis, or other punctuation marks to avoid syntactically invalid code and help reduce compile errors.

Configuration Error

The Configuration Error arises when there are inconsistencies in the way our typescript config file has been set up to meet the requirements of our typescript project. This error affects the behavior of the compiler and can cause problems during compilation.

While there are several types of configuration errors, we will concentrate on a single one,

Error Code

{
  "compilerOptions": {
    "target": "ESNext",
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "module": "ESNext",
    "skipLibCheck": true,
    "allowSyntheticDefaultImports": true,


      /* bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true, //Error: 'resolveJsonModule' cannot be specified without 'node' module resolution strategy.
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",


    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}
Enter fullscreen mode Exit fullscreen mode

From the code snippet above, we got an error indicating that: resolveJsonmodule cannot be specified without the node module resolution strategy."
Given that TypeScript does not provide inherent support for resolving JSON files, the resolveJsonModule is a compile option that allows us to import JSON files as modules in our typescript project. We can't set up our resolveJsonModule without setting our moduleResolution to node, which in this case is set to bundler in our config file.

Fixed Code

{
  "compilerOptions": {
    "target": "ESNext",
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "module": "ESNext",
    "skipLibCheck": true,
    "allowSyntheticDefaultImports": true,


      /* bundler mode */
    "moduleResolution": "node",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",


    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

Enter fullscreen mode Exit fullscreen mode

From the fixed code above, we have set resolveJsonModule to true. We have instructed Typescript to resolve JSON files as modules during the compilation process.

Note: Although the resolveJsonModule option is optional due to the requirement of our project, enabling it in our TypeScript config file provides a more suitable approach for the integration of JSON data in our project to improve development productivity, type safety, and code organization.

Null Error

The Null Error happens whenever you try to access the properties of a variable that is declared with a value of null. Recall, null is one of the primitive data types that signifies the intentional absence of any object value. It is used to indicate that a variable or expression currently has no value.

Error Code

Import {React, useState, useEffect} from react;

function userDetails () {

   Interface User {
     name: string;
     age: number;
   }
   userInfo = { name: 'Philip', age: 22 }

   const [user, setUser] = useState<User | null>(null);

   const getUser = () => {

     setTimeout((() => {
       const fetchUser = userInfo;
       setUser(fetchUser);
     }, 1000);
   }

    useEffect(() => {
     getUser();
    }, []);


  return (
      <>
       <div>
        <p>Name: {user.name}</p>
        <p>Age: {user.age}</p>
       </div>
      </>
  )

}

// Cannot  read properties of null (reading 'name') at userDetails
Enter fullscreen mode Exit fullscreen mode

We created a userDetails component that fetches user data asynchronously and displays its content. The user state is set to null because we don’t have any data initially. After fetching the data, we updated the state but we got an error when we tried to render the data in our UI. What could be the issue? Well, the error is a result of our compiler informing us that the data fetched might not be present in our state because it was initialized as null. So in this case, we have to run a nullcheck to ascertain if the data is present in our state or not.

Fixed Code

return (
  <>
    { user ? (
       <div>
        <p>Name: {user?.name}</p>
        <p>Age: {user?.age}</p>  // No error detected
      </div>
      ) :  ""
    }
  </>
)
Enter fullscreen mode Exit fullscreen mode

We have rectified this error by running a null check using the conditional operator ( ? ). The code expression in our JSX syntax signifies that; If a userexists, then access the data but if the user is null, display an empty string(' '). By employing this approach, we ensure that accessing properties from a nullvalue and the occurrence of null error is effectively prevented.

Note: Null checks are very crucial in development, they give us control over our application by preventing unwanted null reference errors and providing code readability.

Missing Property Error

The Missing Property Error in TypeScript happens when we try to assign a variable to an object or pass it as an argument to a function but the object or function doesn't contain all the properties that are present in that variable.
We will check for errors in both objects and functions.

Error Code in Object

type  CarInfer {
  model: string;
  color: string;
  width: number;
 }

const car: CarInfer = { 
 model: 'Bmw'
 color: 'Black'          
}

// Property 'width' is missing in type '{ model: 'BMW'; color: 'Black' }' but required in type 'CarInfer'.

Enter fullscreen mode Exit fullscreen mode

The error indicates that a property width is included in our CarInfer type, but missing in our car object scope.

Fixed Code in Object

type  CarInfer= {
  model : string;
  color: string;
  width: number;
 }

const car: CarInfer= { 
  model: 'BMW'
  color: 'Black'       
  width: 205    
}
Enter fullscreen mode Exit fullscreen mode

By incorporating the width property in our car object and assigning it a value of 205 as demonstrated in the preceding code, we have successfully resolved the property error within the car object.

Note: When making references to an object, always make sure to include all properties defined in your type object to avoid errors that lead to missing properties in your code base.

Error code in function

function club ( person: {name: string; position: string} ) {

   console.log(`Welcome back, ${person.name}`)
}

const user = {name: 'Francis'};
club(user);

// Property 'position' is missing in type '{ name: string; }' but required in type '{ name: string; position: number; }'
Enter fullscreen mode Exit fullscreen mode

The error code indicates that the position property is present in the function parameter(inside the person object) but missing in the club argument which takes in a user object of only the name property.

Fixed code in Function

function club ( person: {name: string; position: string} ) {

   console.log(`Welcome back, ${person.name}`)
}

const user = {name: 'Francis' position: 'Striker'};
club(user);
Enter fullscreen mode Exit fullscreen mode

Here, we have included the position property in the userobject. Now, the user has been passed as an argument in the club function and we don't get any error.

Note: We should always review our function call to check for possible misplacement of arguments or in this case, whether it tallies with the properties of our parameter.

Type Assertion error

In TypeScript, a Type Assertion error is detected when we assign a type to a value that is not compatible with the actual type of that value. Due to the TypeScript built-in type inference feature, it is expected that the compiler automatically detects the type of a variable from the assigned value.

Error Code

interface UserInter {
 name: string;
 age: number;
};

Const userInfo = {
  name : mark,
  age: 25
};

Const user: UserInter = userInfo as userInter; // type 'string' is not comparable to type 'number'
console.log(user.age); 
Enter fullscreen mode Exit fullscreen mode

If you observed closely from the code snippet above, we created an interface UserInter that specifies the shape of an object with a name property of type string and an age property of type number. We also declared a userInfo object with a name property of type string and an age property of type string. When we tried to reference the userInfo object to the UserInter object using typescript’s type assertion(as userInter), we got an error because the age property of userInfo is a string while that of the UserInter is a number.

Fixed Code

interface UserInter {
 name: string;
 age: number;
};

Const userInfo = {
  name : 'Mark',
  age: 25
};

Const user: UserInter = userInfo as userInter; 
console.log(user.age); 
Enter fullscreen mode Exit fullscreen mode

Here, we have changed the age property of the userInfo object to a number type and we can now reference it to the UserInter object since both of them possess the same shape and properties.

Note: In order to avoid assertion errors like this, it is a good practice to refrain from overusing type assertion in your codes and depend on typescript’s type checking and its type inference feature.

Naming Convention Error

The Naming Convention Error is triggered when there is non-compliance with the suggested conventions of the typescript’s recommended practices that have been put in place for naming variables, functions, and other identifiers in Typescript.

Error Code

interface House {
 name: string;
 color: string;
}

Const peterAvenue = {
 Name: bungalow,
 Color: brown
}

Const getHouse = (house: House) => {
  console.log( `Name: ${house.name), Color: ${house.color}`);
}

getHouse(peterAvenue); // Type '{ Name: string; Color: string; }' is missing the following properties from type 'House': name, color.
Enter fullscreen mode Exit fullscreen mode

From the code snippet above, we encountered a contrast where the interface House is defined with lowercase properties while variable peterAvenue is declared with uppercase properties. To correct this, we must ensure both properties match their right cases.

Fixed Code

interface House {
 name: string;
 color: string;
}

const peterAvenue = {
Name: 'bungalow',
Color: 'brown'
}

Const getHouse = (house: House) => {
  console.log( `Name: ${house.name), Species: ${house.color}`);
}

getHouse(peterAvenue);  // No Error
Enter fullscreen mode Exit fullscreen mode

Looking at the code above, the error has been resolved by following Typescript’s convention of making both peterAvenue and House properties lowercase.

Note: Naming errors are one of the prevalent errors in typescript, we should adhere to consistent naming conventions in our codes so that we can reduce the likelihood of naming errors and increase the efficiency of our application.

Conclusion

Pheeeew! it's a wrap, guys. When developers understand the concept of these errors and implement methods to address them efficiently, they tend to improve code quality, maintainability, and overall development efficiency of their typescript applications.

It is also noteworthy to understand that developers can unleash maximum capabilities and attain favorable results in their projects by taking proactive measures to steer clear of these pitfalls and utilizing typescript’s best practices.

if you find this article interesting; like, share, and comment your thoughts on the comment section below. Gracias Amigo!

💖 💪 🙅 🚩
stanlisberg
Stanlisberg

Posted on May 17, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

What was your win this week?
weeklyretro What was your win this week?

November 29, 2024

Where GitOps Meets ClickOps
devops Where GitOps Meets ClickOps

November 29, 2024

How to Use KitOps with MLflow
beginners How to Use KitOps with MLflow

November 29, 2024

Modern C++ for LeetCode 🧑‍💻🚀
leetcode Modern C++ for LeetCode 🧑‍💻🚀

November 29, 2024