Using React components written in JavaScript within TypeScript code

JavaScript React TypeScript

TypeScript is getting more and more popular. Therefore, it is a great time to start using it if you haven’t already. Chances are, our project has been developed for quite some time. If that’s the case, the best approach could be to introduce TypeScript to the codebase gradually. We might encounter a case where we would like to use React components written in JavaScript within our TypeScript code.

In this article, we look into how to create TypeScript declaration files that allow us to do that. We also learn how we can create interfaces from React prop types.

Declaration files

We can distinguish a type declaration file by the filename extension. Such files’ job is to hold the declarations of our variables and functions without their implementations.

To understand the type declaration files better, let’s create a simple function in JavaScript.

sum.js

We can see that we have an exported function above. Unfortunately, it does not include any types. To deal with that, let’s create a declaration file. The simplest way to do that would be to create a in the same directory.

sum.d.ts

Since we’ve used the default export in our file, we also need to use the default export in .

Above, we declare the function along with its arguments and the return type. The implementation is still in the JavaScript file, so we don’t need to repeat it in the file.

Thanks to doing the above, when we import the function in our TypeScript code, it is fully type-safe.

index.ts

Argument of type ‘”1″‘ is not assignable to parameter of type ‘number’.

We can do a similar thing with variables instead of functions. Although, keep in mind that TypeScript capable of analyzing the JavaScript files to some extent.

constants.js

index.ts

Argument of type ‘”100px”‘ is not assignable to parameter of type ‘number’.

Even though we didn’t create a declaration file for the file, TypeScript properly assigned the and constants with the literal types.

Declaring modules

TypeScript is definitely popular. Therefore, all commonly used libraries should have TypeScript declarations. Even if that’s the case, you might need to use a library that does not have the declarations for some reason. For example, it might be a private library developed by your organization.

A common use case is importing image files. Webpack usually takes care of it under the hood, for example, with the file-loader. Still, TypeScript does not recognize image files as modules.

App.tsx

Cannot find module ‘./logo.png’.

We can easily deal with that by creating a file with a module declaration.

png.d.ts

Above, we declare that all files with the extension export a URL. We could also specify a third-party library in such a way, for example.

Creating declaration files for React components

If we are introducing TypeScript to an organization, chances are there are quite a few React components already in place. To provide an example, let’s create a simple input component in JavaScript.

Input/index.tsx

If we try to import the component in TypeScript as it is, we do get some type safety, but not much.

is a utility shipped with React that can extract the types of the props of a component

Above, we can see that TypeScript can understand our component to some extent. Even though some props such as the are not required, this is not shown in the above types. The prop is described somewhat correctly because we’ve provided a default value. Although, we can improve it further.

Input/index.d.ts

If you are writing class components, use the type imported from React instead of .

You can see that we are free to import additional types in our declaration file above. Creating such declarations results in type-safe React components, even if they weren’t created with TypeScript.

Creating interfaces from prop types

Above, we analyze a JavaScript React component and create a TypeScript interface from scratch. Doing that has the best chance of producing good results, but it takes quite a bit of time. Chances are, the React component we are trying to use already has prop types defined.

To create a TypeScript interface from prop types, we need the utility.

Input/index.d.ts

Doing the above might get us some type-safety. Let’s inspect what props the above declaration produces:

We can see that we can use prop types to generate valid TypeScript interfaces. Unfortunately, they miss some of the essential details, such as the arguments of the function.

Summary

In this article, we’ve looked into how to use JavaScript React components within our TypeScript code. To do that, we’ve learned the basic principles of writing declaration files. We’ve also learned how to create declarations for React components both from scratch and using prop types. Finally, we’ve compared both approaches, and it looks like it might be a better idea to write TypeScript interfaces from scratch in a lot of the cases.

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments