What is the process for importing files with nested namespaces in TypeScript?

Currently, I am in the process of transitioning an established Node.js project into a fully TypeScript-based system. In the past, there was a static Sql class which contained sub-objects with MySQL helper functions. For instance, you could access functions like Sql.user.findById. Additionally, the Sql class included a query function for executing raw MySQL queries without exposing the underlying MySQL connection.

My goal now is to organize this structure by creating a namespace called Sql that houses the query function and then introducing namespaces like Sql.User in the files where the sub-classes were previously located, exporting functions such as findById.

The challenge lies in figuring out how to nest these namespaces while still being able to access the query function within the nested namespaces.

This is what my current setup looks like:

sql.ts:

import * as connection from "./connection";

export * from "./queries/confirmEmail";
export * from "./queries/resetPassword";
export * from "./queries/user";

namespace Sql {
    export function query( ...args: any[] ) {
        return connection.query( args );
    }

    export class Errors {
        static confirmCodeExpired = "45001";
        static confirmCodeNonExistent = "45002";
        static userAlreadyConfirmed = "45003";
    }
}

./queries/resetPassword.ts:

import "../sql";

namespace Sql.ResetPassword {
    type InsertCodeArgs = {
        code: string;
        userid: number;
        canChange: boolean;
    }

    export function insertCode( args: InsertCodeArgs, cb: Nodeback<void> ) {
        Sql.query(
            "CALL insert_reset_code( :code, :userid, :canChange );",
            {
                code: args.code,
                userid: args.userid,
                canChange: args.canChange ? 1 : 0
            },
            cb
        );
    }

    export function removeCode( code: string, cb: Nodeback<void> ) {
        Sql.query(
            "DELETE FROM `resetcodes` WHERE `code` = :code;",
            { code: code },
            cb
        );
    }

    export function checkCodeValid( code: string, cb: Nodeback<boolean> ) {
        Sql.query(
            [
                "SELECT NOW() <= `c`.`expires` AS `valid`, `c`.`canchange` as `canchange`, `u`.`id` AS `userid` FROM `resetcodes` AS `c` ",
                "INNER JOIN `users` AS `u`",
                "ON `u`.`id` = `c`.`userid`",
                "WHERE `code` = :code LIMIT 1;"
            ].join( " " ),
            { code: code },
            ( err, data ) => {
                if ( err ) return cb( err );
                if ( !data || data.length === 0 ) return cb( null, null );

                return cb( null, data[ 0 ].valid > 0, data[ 0 ].userid, data[ 0 ].canchange > 0 );
            }
        );
    }
};

During compilation, I encounter several errors similar to the following:

src\sql\queries\resetPassword.ts(11,13): error TS2339: Property 'query' does not exist on type 'typeof Sql'.

Is there a way to reference the query function from the parent file? Importing { Sql } from "../sql" results in a duplicate definition of Sql, leading to an error stating that

src/sql/sql.ts has no exported member "Sql"
.

Answer №1

By utilizing alias-importing, I was able to resolve my namespace referencing issue within the child namespace files:

import { Sql as sql } from "../sql";

...

namespace Sql.User {
    export function ... {
        sql.query(...);
    }
}

Through this method, the Sql.User namespace is now capable of accessing functions in the Sql namespace located in another file. However, I am still uncertain on how to seamlessly merge the namespaces into one so that importing sql.ts would automatically include Sql.User and its related components. I will need to pose a separate inquiry for further clarification on this matter.

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

Struggling to grasp the error: "NDEFReader is not defined" in a Vue3 web application

In the process of developing a vue3 application, I am integrating the NFC Web API to facilitate reading and writing NFC Chips. My project utilizes typescript, vue routing, and pinia for smooth functionality. Everything runs smoothly when the application i ...

Managing arrays in local storage with Angular 2+

I seem to be missing a crucial element in my endeavor to save and retrieve an array in local storage within my Angular 4 application. The array is fetched from the server and stored in a variable named 'aToDo' with type 'any', like so: ...

Issue connecting database with error when combining TypeORM with Next.js

I am attempting to use TypeORM with the next.js framework. Here is my connection setup: const create = () => { // @ts-ignore return createConnection({ ...config }); }; export const getDatabaseConnection = async () => { conso ...

I'm encountering a typescript error as I migrate a Paho MQTT function from Angular 1 to Angular 2 - what could be causing this issue?

When connecting to my MQTT broker, I am working on several tasks. In my Ionic 2 and Angular 2 application, I have created an MQTT provider. Here is the provider code: import { Component } from '@angular/core'; import { NavController, ViewControl ...

Instructions for enabling the touch slider feature in the Igx carousel component with Angular 6 or higher

Looking to enable the touch slider for Igx carousel using angular 6+? I am trying to implement the igx carousel for image sliding with reference from a stackblitz demo (https://stackblitz.com/edit/github-j6q6ad?file=src%2Fapp%2Fcarousel%2Fcarousel.compone ...

Employing Typescript types in array notation for objects

Can someone please help me decipher this code snippet I found in a file? I'm completely lost as to what it is trying to accomplish. const user = rowData as NonNullable<ApiResult["getUsers"]["data"][number]["users"]> ...

Tips for effectively utilizing the drag and drop feature with the Table Component in Ant Design

Recently, I received a new project from another team, and my client is requesting some changes to the admin page. Specifically, they want to customize the order of data pulled from the database. For instance, they would like to arrange the job positions in ...

What is the best way to retrieve the value of the selected mat-option?

I've been struggling to extract the selected value of a mat-option using this specific HTML and TypeScript code. html <mat-form-field appearance="outline" floatLabel="always"> <mat-label>TRA Type</mat-label> ...

The conditional type in TypeScript is malfunctioning

Upon finishing an article discussing conditional types in TypeScript located at: I have attempted to implement a conditional type in the following function: function convertToIsoString<T extends number|undefined>( timestamp:T ): T extends number ...

Express string declaration in a single TypeScript line

const restrictString = (str: string): string => str.match(/[ab]/g)?.join('') || '' Is there a way to restrict a string to only contain the characters 'a' and 'b' in a one-liner function? I am aware that this can ...

Unlocking 'this' Within a Promise

I seem to have an issue with the 'this' reference in the typescript function provided. It is not correctly resolving to the instance of EmailValidator as expected. How can I fix this so that it points to the correct instance of EmailVaildator, al ...

Enhance Leaflet Marker functionality using Typescript

I am currently tackling a project that involves using Typescript and Leaflet. Traditionally, to extend the leaflet marker in JavaScript, it is done like this: L.Marker.Foo = L.Marker.extend({...}); But when I attempt to do this in Typescript, I encounter ...

Stop Mat-chip from automatically inserting a row upon selection

I am working on preventing the automatic addition of a row by the mat-chip module after a single chip has been selected. Even though the max chip count is set to 1, the input remains enabled and adds a new row beneath it as if the user can still type more ...

Utilizing the 'create' function in sqlite each time I need to run a query

I've been diving into SQLite within the Ionic framework and have pieced together some code based on examples I've encountered. import { Component } from '@angular/core'; import { IonicPage, NavController, NavParams } from 'ionic-a ...

Multiple asynchronous calls in Angular 2

In my Component, there is a function that is supposed to return a value (Promise). This value requires information from two distinct sources: an API call and data from a database. The method in question looks like this: public getValue(): Promise<numb ...

Travis CI's TypeScript build process detects errors before Mocha has a chance to catch them

Instead of a bug, the TypeScript compiler is doing its job but causing my Travis builds to fail. In my package, I have a function named completeRound which accepts a number as its first argument and 3 optional arguments. Since it's in TypeScript, I s ...

Ways to address the issue arising from the utilization of the "as" keyword

Every time I encounter this issue - why must I always provide all the details? type Document = Record<string, any> type FilteredDocument<T extends Document> = {[key in keyof T as T[key] extends (()=>void) ? never : key]: T[key]} const ...

Angular - Automatically update array list once a new object is added

Currently, I'm exploring ways to automatically update the ngFor list when a new object is added to the array. Here's what I have so far: component.html export class HomePage implements OnInit { collections: Collection[]; public show = t ...

Tips for building and implementing Angular URL Parameters for URLs in the form: "component/#/?id=..."

I am currently facing a situation where I have an application with an existing user base. I am looking to avoid disrupting their current links for a smoother transition. However, the previous links are in this format: (server)/viewer/#/?id=12. Please see t ...

What is the best way to include the file name and size as query parameters in Node.js?

To retrieve an image from the folder, a query needs to be passed containing the filename and dimensions like this: localhost:3000/images?filename=myImage&width=100&height=100 The initial objective is to fetch images from the designated folder, res ...