import
is a fundamental keyword in JavaScript and TypeScript that enables you to include code from external modules, promoting code organization and reusability. Import attributes are gaining traction in both JavaScript and TypeScript, marking a new era in developing sophisticated, high-quality web apps.
In this guide, we’ll discuss how to leverage import attributes in TypeScript and JavaScript. We’ll explore how import attributes work, why they matter, their impact on efficiency, stability, and security in web apps, and more.
Import attributes are the latest feature addition to JavaScript’s continually evolving module system. They enable you to include additional metadata for specifying import actions and behaviors.
As the complexity and diversity of web applications increase, managing and loading conditions become crucial for scalability, making import attributes more important now than ever. JavaScript and TypeScript’s module system fell short at handling these requirements for web applications.
TypeScript v5.3 builds on its JavaScript foundation by adding import attributes with the usual type safety and tooling benefits inherent to the language. You can follow the TypeScript proposal for import attributes on GitHub.
Incorporating import attributes in TypeScript and JavaScript projects creates new possibilities for developing efficient, secure, and manageable apps by catering to the sophisticated needs of modern web architectures.
You’ll need to install TypeScript v5.3 to use import attributes. Run this command on your terminal to install TypeScript v5.3 globally:
npm install -g [email protected]
Next, run these commands to create and initialize TypeScript configurations in your project with the name ts-import-attributes
and enter the directory:
mkdir ts-import-attributes cd ts-import-attributes tsc --init
Then, initialize a new Node.js project and install TypeScript in your project as a dependency:
npm init -y npm install typescript --save-dev
Now, you can initialize your TypeScript project by executing this command:
npx tsc --init
The command above creates a tsconfig.json
file in your project. Edit the file to match the following compilerOptions
setup:
// tsconfig.json { "compilerOptions": { "moduleResolution": "node", "target": "es6", "module": "esnext", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true, "outDir": "./dist", "resolveJsonModule": true, } }
Next, create a config.json
file in your project’s directory and add this JSON to the file:
// config.json { "appName": "TS Import Demo", "version": 1.0 }
Finally, add this to your package.json
file:
"type": "module",
Here’s how you can use import attributes to import the config
from the config.json
file:
// index.ts import config from './config.json' assert { type: 'json' }; console.log("The unique feature from config.json is:", config.uniqueFeature);
In this case, the import
statement ensures that the config.json
file is treated as a JSON file.
Note that we’re using the assert
keyword here, and not the with
keyword. Import attributes evolved from import assertions, with the main difference being the keyword.
Another difference is that runtimes can use attributes to guide the resolution of import paths. In comparison, assertions only assert characteristics after loading modules.
As an additional note, Node.js doesn’t currently support import attributes in TypeScript. That’s why we’re using the assert
keyword in this case. You can learn more about this in the TypeScript 5.3 release documentation.
Now, execute this command to compile the program:
npx tsc
The command should transpile your TypeScript program into JavaScript code that looks like this:
import config from './config.json' with { type: 'json' }; console.log("The unique feature from config.json is:", config.uniqueFeature);
Notice that the code is transpiled into the with
keyword in JavaScript and the behaviours are the same.
Since we’re working with the Node.js runtime, execute the compiled JavaScript code with the following node
command:
node dist/index.js
Here’s the output you should expect after running the program:
Now that we’ve seen a simple example of import attributes in a TypeScript app, let’s briefly review how they work from a technical standpoint.
After specifying the import, the TypeScript compiler handles import statements by preserving the attributes for runtime with minimal checks. TypeScript doesn’t process or validate attributes, but it performs basic checks — for example, ensuring that you used the with
keyword correctly and that attributes are valid expressions.
The JavaScript runtime or bundler interprets the import attributes depending on the specific features and behaviors they support. Rollup and webpack already recognize attributes like type: "json"
. If the import attribute’s format doesn’t match the expectations of the runtime or bundler, it may throw an error.
As of the time of this writing, many browsers lack support for import attributes. However, transpilers like Babel can handle them during compilation and convert them to runtime checks that browsers understand.
You can customize the behavior of import attributes to configure their usage. Specifically, import attributes have a resolution-mode
attribute you can use to specify how modules are resolved. The attribute allows you to specify whether modules are resolved traditionally using the require
call or as an ES6 import.
Here’s an example of an import configured to be resolved with the require
keyword:
import type { SomeType } from "some-module" with { "resolution-mode": "require" };
Here’s one that should be resolved as an ES6 import:
import type { SomeType } from "some-module" with { "resolution-mode": "import" };
The resolution-mode
attribute is supported in all module modes and also works with all other moduleResolution
options, such as bundler
or node10
.
Currently, the resolution-mode
attribute is the only stable way you can customize import attributes, although more customization options may be added in the future. You may also be able to explore other ways to extend or customize features in your projects.
Web apps can benefit from some stability and security feature gains when using import attributes in TypeScript.
The security improvements that import attributes offer emphasize intentional imports, sub-resource integrity, and compliance with CSPs:
Meanwhile, the stability benefits of import attributes emphasize better module management and ergonomics with clarity during development:
In summary, TypeScript’s import attributes feature significantly improves security and stability. They offer a more secure, controlled, and predictable environment for developing and maintaining robust web applications.
import
attributesAs useful as import attributes are, they have some limitations and tradeoffs. For example, you may face compatibility issues while using import attributes in your new projects since this new feature may not be supported by many development environments.
In addition, the resolution-mode
attribute adds complexity to the module resolution process. You need to understand underlying concepts to take advantage of this feature.
Furthermore, while import attributes do provide some security improvements to your project, using them improperly may result in some potential security vulnerabilities:
You may also encounter some of these pitfalls while working with import
attributes:
There are various ways to resolve each of these errors that are not specific to import attributes. You can read about resolving common TypeScript module problems or resolving errors during runtime type-checking, but we won’t go into detail about solutions in this article.
import
attributesWhile import attributes can help improve security and scalability in your TypeScript projects, there may be cases where you want to avoid the limitations and errors associated with them. Instead of using import attributes, you can use a few different methods to achieve similar functionality.
For example, you can explicitly separate type imports from module imports to differentiate type-only imports from code imports. In addition, depending on your project’s requirements, you might consider leveraging dynamic imports through require
statements or organizing your codebase to minimize the need for import attributes.
In this tutorial, we saw how the straightforward process of setting up and using import attributes in TypeScript can enhance scalability and security. We covered why import attributes matter, how they work from a technical perspective, and how to configure your TypeScript environment to implement import attributes.
While import attributes provide many benefits, we also explored some of their drawbacks and common pitfalls. To avoid these issues, we introduced a few alternate methods that can help you achieve similar outcomes.
Leveraging import attributes can improve your program quality and development experience. I hope this guide is useful as you explore ways to implement them in your projects. Happy coding!
Debugging code is always a tedious task. But the more you understand your errors, the easier it is to fix them.
LogRocket allows you to understand these errors in new and unique ways. Our frontend monitoring solution tracks user engagement with your JavaScript frontends to give you the ability to see exactly what the user did that led to an error.
LogRocket records console logs, page load times, stack traces, slow network requests/responses with headers + bodies, browser metadata, and custom logs. Understanding the impact of your JavaScript code will never be easier!
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowCompare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.