What is the best way to utilize Type Aliases and Interfaces to define TypeScript variables in declaration files within a project?

Imagine the folder/directory structure outlined below.

[src: App]
  |
 + tsconfig.json
 + [@types]
      |
      + index.d.ts   (contains type aliases and interfaces for App)
 + AppSharedCode.ts   (code shared by *.ts files in subdirectories)
 + [ThingCreator]
      |
      + ThingCreator.ts
      + tsconfig.ts
 + [ThingUser]
      |
      + ThingUser.ts
      + tsconfig.ts

[Lib]
  |
  + tsconfig.json
  + [@types]
     |
     + index.d.ts  (contains type aliases and interfaces for Lib)
  + [src]
     |
     + myLib.ts 

The project showcases two web app components, one creating a meeting agenda and another using it. To avoid naming conflicts, the main *.ts files were separated into subdirectories with their own tsconfig.json files. There are total of four tsconfig files used.

A directory named @types houses an index.d.ts file which was intended to enhance understanding of TypeScript usage in VS Code during the transition from JS to TS. Unfortunately, this approach did not prove helpful.

In my *.ts files, I can type variables that represent HTML DOM elements without importing the declarations from lib.dom.d.ts. For example:

    let taElem: HTMLTextAreaElement;

If we consider the contents of the index.d.ts file under the App src/@types:

    declare module "AgendaTypes" {
        interface IAgendaItem {
            headline: string;
            children: IAgendaItem[];
            meetingNote: string;
        }
    }

And within the AppShareCode.ts file:

    import AgendaTypes from "AgendaTypes";

To utilize IAgendaItem in the ts source, dot notation must be used or declarations should be made within a namespace:

    let anItem: AgendaTypes.IAgendaItem;

Some questions arise:

  1. What is the correct way to declare/export type aliases/interfaces in declaration files so they are visible throughout the project for the compiler? Can all interface/type alias definitions be enclosed in braces for simplified usage without dot notation?
  2. How can the names of type aliases and interfaces be accessed between *.ts files in the App and the Lib sources? Is there a tsconfig setting or do we require import statements?
  3. Regarding global variables, should they be collected and defined with type aliases/interfaces in a *.d.ts file or gathered in a single *.ts file?

I have encountered challenges when trying to import the Lib code. Despite setting composite as true in all tsconfig files and referencing paths in the root tsconfig file, the issue persists.

As I delve into TypeScript amidst a comprehensive effort to convert JavaScript projects, I acknowledge the discipline it brings to JavaScript development.

Note: A shorter version of this post was initially planned but ended up being discarded during revision.

Several related threads on similar topics lacked definitive answers or clarifications from the posters. One somewhat relevant answered thread can be found here.

Answer №1

I must admit, your folder structure and the abundance of tsconfig.json files scattered throughout your project are quite puzzling to me. If you're in the process of refactoring, it might be worth reconsidering the goals you have set for yourself. Typically, most projects only require a maximum of two tsconfig.json files, and placing a tsconfig config file inside the source (src) folder is not common practice.

Despite these organizational challenges, I notice that your queries mainly revolve around typescript-related issues, so allow me to address those.

When it comes to declaring/exporting type aliases/interfaces in declaration files, there seems to be some confusion on what constitutes the proper approach. While examining *.d.ts files in *node_modules/@types and lib.dom.d.ts can provide some insights, establishing a clear pattern may prove challenging. Is it feasible to encapsulate all interface and type alias definitions within braces to ensure their visibility across the entire project for the compiler? The objective is to utilize the type alias or interface name directly without resorting to dot notation for namespaces or "module," similar to how HTMLTextAreaElement is referenced without dot notation from the library.

Ensuring that Typescript can access your *.d.ts file (i.e., integrating it into your included files or making it visible through typeroots) should facilitate the seamless declaration of types globally. Importing them is unnecessary—and impossible—unless they are housed in a *.ts file.

Transitioning to the *.ts source files realm, what is the appropriate method to enable the sources to recognize the names of type aliases and interfaces, particularly between files in the App and Lib sources? Does this necessitate a tsconfig setting or an import statement?

You can handle the integration of these declarations in the same manner as with declaration files: Ensure that they are incorporated into the corresponding tsconfig.json file linked to the targeted folder.

In terms of global variables within this project, their inclusion is notable. These variables are frequently DEFINED in source files where they are initialized or predominantly utilized, although referenced by other *.ts files. Would consolidating them in a single *.ts file be advisable? Alternatively, should they be aggregated, defined, and declared alongside type aliases and interfaces in the *.d.ts file?

The decision on whether to collect global variables in a single constants.ts file or incorporate them alongside type aliases and interfaces in a *.d.ts file ultimately hinges on personal preference. Generally speaking, many projects opt to house constant values in a dedicated constants.ts file within the source directory, allowing for easy access throughout the project.

Note: It's important to note that constants cannot be declared in declaration files, given the inherent restriction on importing entities from such files.

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

Killing the command prompt in Typescript: A step-by-step guide

Is there a way to completely close the cmd where the typescript file is running but unable to do so? How can this be achieved? console.log('This ts file must be terminate itself'); let asdef = process.pid; let asdeff = process.ppid; const {exe ...

A notification pop-up will only appear the first time after sending a repeated action

When testing my snackBar functionality by inputting incorrect user credentials multiple times and submitting the form, I encountered an issue. The snackBar only appears the first time, not every time an error or success message is dispatched. Below is the ...

Event triggered by clicking on certain coordinates

Just starting with @asymmetrik/ngx-leaflet and Angular, so this might be a beginner's issue... I'm working on an Angular.io (v5) project that incorporates the @asymmetrik/ngx-leaflet-tutorial-ngcli Currently, I'm trying to retrieve the coo ...

Ignoring the no-unused-vars rule from StandardJS even though variables are being used

Within my Typescript React project, I have declared the following: export type NavState = { mounted: boolean } I then proceeded to use this within a component like so: import { NavState } from '../../models/nav' class Nav extends React.Compon ...

Can someone explain why the Next 13 API route is showing up as empty?

I am currently working with Next 13 and I am attempting to create a simple API route. My goal is to have a: "hi" returned when I visit localhost:3000/api/auth. Despite not encountering a 404 error or any errors in the terminal or console, I can&a ...

The Kubernetes cluster unexpectedly closes down following a period of processing

My GCP cluster is hosting a NodeJS server. The server functions flawlessly when run locally, but mysteriously stops without any error messages when I attempt to send a post request to a specific route. This post request is supposed to trigger the sending o ...

Is it possible to extend an Angular component and then use the base component in an ngFor loop?

Can Angular components be extended? And if so, is it possible to create a list of diverse components (using an ngFor loop) that all extend a common base component? For instance, could a custom menu bar display various types of menu items, such as dropdown ...

Unable to attach eventName and callback to addEventListener due to the error message stating 'No overload matches this call'

I am attempting to attach an event listener to the input element stored within a class method. This method takes a props object containing eventName and callback. public setTextFieldInputListener({ eventName, callback }: TextFieldListenerProps): void { ...

I possess a JSON array object and need to identify and extract the array objects that contain a specific child node

const jsonArray = { "squadName": "Super hero squad", "homeTown": "Metro City", "formed": 2016, "secretBase": "Super tower", "active": true, "members": [ { "name": "Molecule Man", "age": 29, "secretIdent ...

Metamorphosed Version.execute SourceText and TypeScript Writer

I'm currently working on transforming a TypeScript source file and I have successfully made the necessary changes to the code. Despite seeing my transformed node in the statements property of the transformed source file, the SourceFile.text property d ...

Typescript indicates that an object may be 'undefined' when the value is an empty string

I'm new to Typescript and currently working on converting our application from React JSX to TS. If I'm misunderstanding the error, please let me know. I've encountered the error message Object is possibly 'undefined' related to a ...

Typescript controller inheritance leading to Error: $injector:unpr Unknown Provider due to minification

LATEST UPDATE: 2019/07/16 The issue I am facing is actually a result of misusing $inject. Instead of declaring it as private $inject in api-service.ts, it should have been public static $inject = [...]. During the minification process, explicit injection ...

The type 'MutableRefObject<undefined>' cannot be assigned to the type 'LegacyRef<HTMLDivElement> | undefined'

I have created a customized hook that takes a ref object and observes its behavior: import { useState, useEffect, MutableRefObject } from "react"; const UseOnScreen = (ref: MutableRefObject<undefined>) => { const [isIntersecting, setI ...

Is it possible for RouteData in Angular 2 to transmit variables from a parent component to routed components?

How can I pass a variable from my AppComponent to CoursesComponent using RouteConfig? The "data" property in route config seems to only accept constant parameters and cannot recognize "this". Is there a workaround for this limitation? If not, what is the ...

I attempted to execute an art configuration on Metaplex, but I keep encountering the same issue. Despite numerous attempts to modify various settings, the problem persists

Error encountered while compiling TypeScript code on desktop using ts-node to generate art configuration traits: Unable to find module 'commander' or its corresponding type declarations. Unable to find module '@project-serum/anchor' or ...

I am experiencing difficulties with broadcasting and attending events

File.js scope.menuItemClick = function (def, callbackText, keepMenuOpen) { console.log(def); if(def.automationId === "Print"){ console.log("before send"); $scope.$root.$broadcast("printingData","my Data"); console.log("after send"); } Nex ...

What could be causing MongoDB to not delete documents on a 30-second cycle?

Having trouble implementing TTL with Typegoose for MongoDB. I am trying to remove a document from the collection if it exceeds 30 seconds old. @ObjectType("TokenResetPasswordType") @InputType("TokenResetPasswordInput") @index( { cr ...

TypeScript mandates the inclusion of either one parameter or the other, without the possibility of having neither

Consider the following type: export interface Opts { paths?: string | Array<string>, path?: string | Array<string> } The requirement is that the user must provide either 'paths' or 'path', but it is not mandatory to pa ...

Tips on handling multiple Redux toolkit CreateApi interceptors

I came across this solution here for implementing a reAuth baseQuery in Redux Toolkit. I have several backend services that all use the same refresh token concept. Is there a way to create a single baseQueryAuth function that can be used by multiple creat ...

When the page is refreshed, Vercel's Next.JS success/error pattern is thrown due to the "window is not defined" error

Currently, I am working on enhancing a Next.js website that is hosted on Vercel. Upon deploying the page, I encountered the following error initially: GET] / 17:53:00:19 2022-09-12T14:53:00.262Z 938c1a2e-ce7c-4f31-8ad6-2177814cb023 ERROR Uncau ...