7 Common Errors And Possible Fix Every Typescript Developers Should Know.
Published: 2023-05-17 07:47:34

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

```javascript
let firstName: string = "Felix";
firstName = true; // Type error: Type 'boolean' is not assignable to type ‘string’
```
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**

```javascript
let firstName: string = "Felix";
firstName = 'Joshua';   // No error detected 
```
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**

```javascript
const userName = (name: string) => {
  console.log (`Hey! ${name}`)
}
userName("Frank); // Syntax Error: Unterminated string literal
```
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**

```javascript
const userName = (name: string) => {
  console.log (`Hey! ${name}`)
}
userName("Frank"); // No error detected
```
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**

```javascript
{
  "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" }]
}
```

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

```javascript
{
  "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" }]
}

```
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**

```javascript
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
```
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 `null `check to ascertain if the data is present in our state or not.

**Fixed Code**

```javascript
return (
  <>
    { user ? (
       <div>
        <p>Name: {user?.name}</p>
        <p>Age: {user?.age}</p>  // No error detected
      </div>
      ) :  ""
    }
  </>
)
```
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 `user`exists, 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 `null `value 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**

```javascript
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'.

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

**Fixed Code in Object**

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

const car: CarInfer= { 
  model: 'BMW'
  color: 'Black'       
  width: 205    
}
```
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**

```javascript
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; }'
```

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

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

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

const user = {name: 'Francis' position: 'Striker'};
club(user);
```
Here, we have included the position property in the `user `object. 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**

```javascript
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); 
```
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**

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

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

Const user: UserInter = userInfo as userInter; 
console.log(user.age); 
```
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**

```javascript
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.
```
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**

```javascript
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
```
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!