Table of content
- Introduction
- What is typescript
- Type Error
- Syntax Error
- Configuration Error
- Null Error
- Missing Property Error
- Type Assertion Error
- 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’
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
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
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
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" }]
}
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" }]
}
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
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
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
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
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
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
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
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
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
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
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!
Top comments (2)
Thanks you so much @stanlisberg for sharing 🙏
Thanks for reading @gassaihamza .👍