Securely import TypeScript modules from file paths that are dynamically determined during execution

Imagine you have a structure of TypeScript code and assets stored at a specific URL, like between a CDN and a debug location. You want to import the main module and ensure the rest of the structure is imported correctly only when needed, without repeating the loading path multiple times.

In vanilla JavaScript, you might achieve this with code similar to:

export class MyModule {
    private dependentModulePromise;

    constructor(rootpath) {
        this.dependentModulePromise = import(rootpath + '/dependentModule');
    }
}

However, in TypeScript, you'd aim for maximum type safety. Using a type assertion is necessary for the dynamic string import, but how can you inform TypeScript about the type being loaded without conflicts or synchronously bundling the module with tools like Webpack?

An attempt was made with the following approach:

import * as DependentModule from '/dependentModule';

export class MyModule {
    private dependentModulePromise: Promise<DependentModule>;

    constructor(rootpath) {
        this.dependentModulePromise = import(rootpath + '/dependentModule') as Promise<DependentModule>;
    }
}

Unfortunately, an error occurs stating that the namespace DependentModule cannot be used as a type.

Answer №1

There is a workaround that may work for you: if the file /dependentModule has a default export instead of exporting a namespace, everything should function properly.

// In this example, dependentModule exports a class
import { default as DependentModule_TYPE_ONLY } from '/dependentModule';

export class MyModule {
    private dependentModulePromise: Promise<new () => DependentModule_TYPE_ONLY>;

    constructor(rootpath) {
        this.dependentModulePromise = import(rootpath + '/dependentModule') as Promise<new () => DependentModule>;
    }
    
    public async doStuffWithDependentModule() {
        const DependentModule = await this.dependentModulePromise;
        const m = new DependentModule();
        // perform type-safe operations with m here
    }

}

It's ideal if the default export aligns with an interface or type definition elsewhere so that the promise can be cast accordingly (for instance, if DependentModule conforms to IInterfaceOfInterest, then the import promise should be

Promise<new () => IInterfaceOfInterest>
).

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

Ensuring a User has an Image in MySQL Using Angular 6

As part of my development process, I am working on creating a new user and sending their information along with an image to a MySQL database. The process involves sending a user object with form data through the following component.ts file: subscribeUser() ...

Can you explain the distinction between declaring a map in TypeScript using these two methods?

When working in TypeScript, there are two different ways to declare a map. The first way is like this: {[key:number]string} This shows an example of creating a map with keys as numbers and values as strings. However, you can also define a map like this: M ...

Using decorators in TypeScript, can we define new class attributes?

Here is an example code snippet: function Getter(target: any, key: string): void { let getter = () => this[key]; /* create "foobar" property from "_foobar" */ Object.defineProperty(target, removeUnderscores(key), { get: getter, enumerabl ...

Execute the render function of the components that have been passed as

I've been grappling with a challenge lately - figuring out how to invoke a passed component's render function within another function. Let's say I have two functions named A and B: export const A = (value: any) => { return ( <div& ...

issues arise post-transpilation with creating errors

In order to practice, I decided to create a basic TypeScript project. If it could be helpful, here is my ts.config: { "compilerOptions": { "target": "es2016", "module": "commonjs", "outDir": "./dist", "esModuleInterop": true, "forceC ...

Change prompt-sync from require to import syntax

In my Node project, I have integrated the prompt-sync module. const prompt = require('prompt-sync')(); const result = prompt(message); To maintain consistency in my TypeScript code, I decided to switch from using require to import. In order to ...

Encountering ReferenceError when attempting to declare a variable in TypeScript from an external file because it is not defined

Below is the typescript file in question: module someModule { declare var servicePort: string; export class someClass{ constructor(){ servicePort = servicePort || ""; //ERROR= 'ReferenceError: servicePort is not defined' } I also attempted t ...

"An issue has been identified where TSLint and VSCode fail to display red underlines in

I am currently working on a single .ts file where I am experimenting with configuring tslint and tsconfig. To test the configuration, I intentionally added extra spaces and removed semicolons. Despite running the command tslint filename.ts and detecting e ...

TypeScript is unable to detect the .sequelizerc configuration file

I have a file called .sequelizerc which contains the following configuration: const path = require('path'); module.exports = { config: path.resolve('.', 'src/config/sequelizeCLIConfig.json'), 'migrations-path': ...

Converting a string to the Date class type in Angular 4: A comprehensive guide

Within my .ts file, I have a string that looks like this: const date = "5/03/2018"; I am looking to convert it into the default date format returned by Angular's Date class: Tue Apr 03 2018 20:20:12 GMT+0530 (India Standard Time) I attempted to do ...

TypeScript - Converting into individual compiled files

Currently, I am working on a project that consists of lengthy source files. While this is advantageous for imports, it poses challenges in terms of maintenance. For instance: /main/core.ts export type Foo { ... } export interface Bar { ... } export cla ...

Unable to retrieve values using any = {} in TypeScript Angular 8

import { Component, OnInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { enableProdMode } from '@angular/core'; enableProdMode(); @Component({ selector: 'app-home', templat ...

Utilizing Vue and Typescript for efficient dependency injection

After attempting to use vue-injector, I encountered an issue as it was not compatible with my version of Vue (2.6.10) and Typescript (3.4.5). Exploring other alternatives, there seem to be limited options available. Within the realm of pure typescript, t ...

When working on styling a different Styled Component, how should one define the type of props required?

I'm currently working on a NextJS project using styled components and typescript. I have customized a div element like this: export const ClippedOverlay = styled( ( props: React.DetailedHTMLProps< React.HTMLAttributes<HTMLDivElement& ...

Leveraging File functionality in TypeScript

In the process of developing a web application with Angular 4 and Typescript, I encountered an issue while attempting to retrieve the date of a file for upload. Specifically, when trying to access the lastModified property of a File object, Typescript retu ...

Receiving the error notification from a 400 Bad Request

I'm having trouble showing the errors returned from an API on my Sign up form when a user submits invalid data. You can check out the error response in the console here: console ss This is my approach in RegisterComponent.ts: onSubmit() { this.u ...

What is the correct way to implement fetch in a React/Redux/TS application?

Currently, I am developing an application using React, Redux, and TypeScript. I have encountered an issue with Promises and TypeScript. Can you assist me in type-defining functions/Promises? An API call returns a list of post IDs like [1, 2, ..., 1000]. I ...

Is it possible to conceal dom elements within an ng-template?

Utilizing ng-bootstrap, I am creating a Popover with HTML and bindings. However, the ng-template keeps getting recreated every time I click the button, causing a delay in the initialization of my component. Is there a way to hide the ng-template instead? ...

Outputting double columns with Typescript Sequelize associations

I am currently in the process of constructing table models using sequelize along with typescript. Here is an example of one of my models: 'use strict'; import { Model, InferAttributes, InferCreationAttributes, CreationOptional } from 'seque ...

Is it possible to retrieve the child state value in the parent component using useRef in ReactJS with TypeScript (hooks)?

I am currently learning Typescript and I am trying to figure out how to pass child state values to the parent component using a ref when a button is clicked in order to update the reducer values. However, I keep running into errors when I try to pass a ref ...