Are `import type` and `import()` the same thing?

Is there a difference between?

import type { Foo, Bar as Baz } from './'

and

type Foo = import('./').Foo
type Bar = import('./').Baz

It's important to note that the import() here is not a dynamic import but rather import types introduced in TypeScript 2.9. You can test both examples on the TypeScript playground to confirm their syntax and validity.

I prefer using import type while still generating declarations for TS < 3.8.

If the statement above holds true, I could potentially apply an AST transform to the resulting declaration files.

Answer №1

Although commonly used interchangeably, they are not actually equivalent. There exist two key differences between them that hold significance based on the context.

import type transforms a file into a module.

The TypeScript compiler distinguishes whether the top-level scope of a TypeScript file is module-scoped or globally scoped by detecting the presence of any import or export declarations. In this regard, import type functions as an import declaration, meaning that if it stands alone as the only import/export statement in the file, replacing it with a type alias would shift the classification of the file from a module to a script. This distinction becomes relevant when dealing with files (typically .d.ts files) that require global scope but necessitate referencing types from a module - where you are left with no choice but to utilize type Foo = import(...).

import type can encompass both value and namespace connotations.

By creating a type alias using type Foo = import('./').Bar, Foo exclusively represents a type, even if Bar possesses both type and value significances (e.g., class Bar {}). The declaration completely disregards the value aspect of Bar. Essentially, import type directly points to the complete symbol for Bar along with all its implications; it merely establishes a syntactic validation to prevent its utilization in a context that would be emitted to JS (considering that the import statement will be erased in JavaScript). This distinction bears relevance in various scenarios, best elucidated through an example:

import type { EventEmitter as EE1 } from "events";
type EE2 = import("events").EventEmitter;

// Valid since 'declare' signifies that 'Foo1' is not utilized in an emitting position.
declare class Derived1 extends EE1 {}

declare class Derived2 extends EE2 {}
//                             ^^^
// Error: 'EE2' solely refers to a type but is being employed as a value here.

type EventEmitterCtor1 = typeof EE1; // Valid
type EventEmitterCtor2 = typeof EE2;
//                              ^^^
// Error: 'EE2' just pertains to a type but is treated as a value here.

const x = EE1;
//        ^^^
// Error: 'EE1' cannot serve as a value due to being imported via 'import type'

const y = EE2;
//        ^^^
// 'EE2' uniquely denotes a type but is perceived as a value here.

(Access Playground link)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The presence of 'eventually' in the Chai Mocha test Promise Property is undefined

I'm having trouble with using Chai Promise test in a Docker environment. Here is a simple function: let funcPromise = (n) => { return new Promise((resolve, reject) =>{ if(n=="a") { resolve("success"); ...

A guide on integrating third-party npm modules/packages into an Angular 8 application

As someone who is new to Angular and TypeScript, I am finding it challenging to add a 3rd party module or package to my Angular app. After spending hours searching online, I have yet to come across a simple guide for this process. The specific problem I a ...

Troubleshooting issue with @Input not updating model in parent component in Angular 2

The scenario I am facing involves entities that own a Pessoa, with one of them being an Administrador. To handle this, I created a component to encapsulate the Pessoa data on CRUD forms. I linked the administrador.pessoa property to my new PessoaFormCompon ...

Combining Firebase analytics with an Ionic 3 application using the Ionic Native plugin

I placed the GoogleService-Info.plist file at the root of the app folder, not in the platforms/ios/ directory. When I tried to build the app in Xcode, an error occurred in the following file: FirebaseAnalyticsPlugin.m: [FIROptions defaultOptions].deepLin ...

Types are present in 'typeRoots' but will only function if specifically included

Trying to implement the grecaptcha types package (@types/grecaptcha) in my project. In my tsconfig, it's configured like this: "typeRoots": [ "node_modules/@types" ], However, when attempting to use the provided grecaptcha object or RecaptchaV2, I ...

Creating a nested observable in Angular2: A step-by-step guide

Currently, I am exploring a new approach in my Angular2 service that involves using observables. The data source for this service will initially be local storage and later updated when an HTTP call to a database returns. To achieve this dynamic updating of ...

Developing applications with TypeScript in combination with Express()

My goal is to integrate the latest version of Express with node.js using TypeScript. However, I have encountered an issue with the express.d.ts file provided by Microsoft in the samples. It seems to be based on versions prior to 3.0.x. In older versions, y ...

Importing a class from a JavaScript file in Typescript: a step-by-step guide

I need help with the following: Importing a js file that defines a class: ./myClass/index.js Declaring the public methods of MyClass (unsure of where to do this, whether in index.ts or another declaration file) Creating a typescript file that exposes the ...

Deactivating upcoming weeks according to the year in Angular 8

In the user interface, there are dropdowns for selecting a year and a week. Once a year is selected, the list of weeks for that year is displayed in the week dropdown. Now, the requirement is to disable the selection of future weeks. For example, for the ...

Is it possible to create a class object with properties directly from the constructor, without needing to cast a custom constructor signature

class __Constants__ { [key: string]: string; constructor(values: string[]) { values.forEach((key) => { this[key] = key; }); } } const Constants = __Constants__ as { new <T extends readonly string[]>(values: T): { [k in T[num ...

After upgrading to node version 20 and other dependencies, encountering ERR_REQUIRE_ESM issue

Attempting to update node from version 16 to 20 has led me to also consider upgrading some other libraries simultaneously. Upon trying to start my backend after completing the updates, the following error occurred: % yarn run dev [nodemon] 3.0.1 [nodemon] ...

Timing and framing challenges arise when working with Jasmine-marbles and incorporating hot and cold features

If you want to check out a quick demo, feel free to download it here: https://stackblitz.com/edit/angular-vczzqp. Simply hit export in the top right corner and then in your preferred terminal run install and ng test with your favorite browser. It seems li ...

Challenges with invoking functions within ngFor loop during unit testing in Angular 12

I am currently learning about unit testing and I am facing an issue with calling a function inside an *ngFor loop in an Angular 12 application. I have an observable that contains an array of objects and it is working correctly, iterating through the data p ...

When compiling TypeScript in Visual Studio 2017, the error "Name 'Office' cannot be found" is displayed

Currently, I am in the process of converting a Word VSTO Add-in into the new Office Add-in format. After installing the most recent version of Visual Studio 2017 Community, I encountered an issue with using TypeScript in my code. Despite my efforts, I am u ...

CompositeAPI: Referencing HTML Object Template - Error TS2339 and TS2533 when using .value to access Proxy Object

Having trouble referencing an element in VueJS 3 CompositeAPI. In my current implementation, it looks like this: <div ref="myIdentifier"></div> setup() { const myIdentifier = ref(null); onMounted(() => { console.log(myIden ...

"Typedoc indicates that no entry points were detected"

This is my main.ts file, but I had renamed it to index.ts later. However, I still encountered the same error multiple times as shown in the terminal output below: https://i.sstatic.net/hFHmX.png Below is the content of my tsconfig.json file: https://i.s ...

Receiving a conduit from the fuel supplier with only limited information on hand

I am designing a service that will utilize pipes as templates. In order to accomplish this, I require access to the registered pipes. The final code structure should resemble the following: @Injectable() class MyService { constructor(private injector ...

Adjusting the dimensions of the cropper for optimal image cropping

I am currently working on integrating an image cropper component into my project, using the react-cropper package. However, I am facing a challenge in defining a fixed width and height for the cropper box such as "width:200px; height:300px;" impo ...

Improving a lengthy TypeScript function through refactoring

Currently, I have this function that I am refactoring with the goal of making it more concise. For instance, by using a generic function. setSelectedSearchOptions(optionLabel: string) { //this.filterSection.reset(); this.selectedOption = optionLa ...

Obtain the data from onTouchTap action

Currently, I have a class that is returning an event to the parent. My goal is to extract the number of the touched button (the label on RaisedButton). Although I am successfully returning the event, I am unable to locate the desired information when I l ...