What is the proper method for utilizing TypeScript declarations (*.d.ts) and interfaces?

When working with interfaces in TypeScript, there are two main approaches to consider. The first involves defining them in regular .ts files and importing them as needed. The second option is to define the interfaces in .d.ts files and let the compiler discover them automatically from node_modules/@types or by specifying paths in typeRoots within tsconfig.json. This allows the interfaces to be accessible throughout the project without direct imports.

In my current setup, I have separate client (React) and server (Express) projects, both written in TypeScript. To share common interfaces between these projects while keeping dependencies separate, I moved the shared interfaces to a standalone project stored in declaration files. I then included this project as a dev dependency using the following syntax:

"@types/my-definitions": "git+ssh://[email protected]/myaccount/my-definitions.git"

This configuration enables the TypeScript compiler to automatically recognize the interfaces from node_modules/@types without the need for explicit imports.

My question is, is this approach considered best practice? Should I instead store the interfaces in regular .ts files, import the shared project as a standard dependency, and explicitly import the interfaces when needed? What are the advantages and disadvantages of each method?

Answer №1

.d.ts files are created as part of a typescript project, along with the compiled JS files, from your original .ts code.

Usually, these files are imported into your project rather than automatically detected because they are in a specific folder.

However, if you are working with environment JS globals like DOM/BOM/NodeJS, you may want to place your .d.ts files in a designated folder so they are accessible to all of your code without needing to import them explicitly.

On the other hand, when using a JavaScript library, it is recommended to import the library via package.json and configure TypeScript to resolve modules by searching through node_modules.

For instance,

If you use document.createElement() and require an HTMLElement, with the right environment definitions, you won't need to import the document object separately.

However, in the case of Angular, importing an angular class like Component will require an explicit import statement:

import {Component} from "@angular/core"

TypeScript will then search for the necessary .ts files in node_modules/@angular/core. While raw .ts files are available, they are typically not distributed alongside the JavaScript output of a TypeScript project; usually only the compiled JS and corresponding .d.ts files are provided.

To sum up,

It's advisable to treat your reusable code as a third-party library, similar to how you would handle an angular library - by importing it directly. Avoid cluttering the global environment with unnecessary definitions (there are already plenty of those).

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

Ways to exclude an object field in Angular 7

Is there a way in Angular to exclude specific fields before making an http call, similar to the @JsonIgnore annotation in Java? For instance: Given this object: {id: 1, libelle: 'test', mustIgnore: 'test'}; I am looking to have it tr ...

Solving the Path Dilemma in TypeScript Functions within the Firebase Environment

My Firebase project utilizes TypeScript functions with the following directory structure: - functions - src - index.ts - shared - other.ts - tsconfig.json - package.json Within my tsconfig.json file, the configuration is as follows: { &q ...

Receiving an eslint error while trying to integrate Stripe pricing table into a React web application

If you're looking to incorporate a Stripe documentation code snippet for adding a stripe-pricing-table element, here's what they suggest: import * as React from 'react'; // If you're using TypeScript, don't forget to include ...

Maintain the specific type based on the provided data, rather than the default value, when a related generic is defined

When it comes to unit tests, I prefer a more flexible approach with dynamic generic types that eliminate the need for type casting. I want T to be open-ended, but if I specify a type, I expect to receive an exact match. For R, I need it to precisely matc ...

The unit test is not passing due to inconsistencies between the mock data generated in the constructors and the original mock data

Currently, I am delving into the world of unit testing and have created a test to work on. Here is what I have so far: const EXEPECTED: MergedFood = { id: '1', name: 'test mergedFood', ingredients: { '2': ...

Utilize the UserService in NestJs to enhance security within the RolesGuard functionality

In my application, I have a module called UserModule that exports the UserService. Here is an example of how it is done: @Module({ imports: [ MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]), MongooseModule.forFeature([{ name: ...

Why is it not possible to convert from any[] to MyType[] in TypeScript?

Within TypeScript, the any type allows for casting to and from any arbitrary type. For example, you can cast from a variable of type any to a variable of type MyArbitraryType like so: var myThing: MyArbitraryType; var anyThing: any; myThing = anyThing; / ...

Is there a way to adjust the height of mat-sidenav-content to be 100%?

I'm having trouble scrolling down my mat-sidenav-content to reach the bottom where my pagination is located. When I try using fullscreen on mat-sidenav-container, my mat-toolbar disappears. How can I adjust my mat-sidenav-content based on the content? ...

Could not find the 'injectTapEventPlugin' export in the dependencies of Material-UI related to 'react-tap-event-plugin'

Currently, I am working on a project that involves using react, typescript, material-ui, and webpack. An issue has arisen with importing the injectTapEventPlugin function from the dependency of Material-UI, react-tap-event-plugin. The specific error messag ...

When using Angular 2, the array.splice() function is causing the elements to be removed from the

I am currently working with an HTML table that has default checked rows. <table> <tr> <th></th> <th>Id</th> <th>Name</th> <th>Initial</th> </tr> ...

The `$refs` variable in Vue can be used to reference a specific Vue component within a class-st

Would it be possible to access this.$refs.label? I am using the package vue-property-decorator. Below is the content of the component: <template> <div> <label ref="label">asd</label> </div> </template> <scr ...

Error encountered: No matching overload found for MUI styled TypeScript

I am encountering an issue: No overload matches this call. Looking for a solution to fix this problem. I am attempting to design a customized button. While I have successfully created the button, I am facing the aforementioned error. Below is my code ...

Make sure to always include a trailing comma when defining a single type parameter T. Here's an example: `<T,>`

Ensure that a single type parameter T includes a trailing comma. For example: <T,>. (3:29) export const toggleItem = <T>( How can I resolve this error? Adding <T,> causes Prettier to remove the "," when saving. I have not made any change ...

What is the best way to iterate through an enum?

The type 'string' cannot be assigned to the type 'online' or 'offline'. I must be overlooking something, but I'm not sure what it is. enum StatusOptions { ONLINE = 'ONLINE', OFFLINE = 'OFFLINE', ...

Error: React is not defined and cannot create an element

I've been working on transitioning a functional ReactJS application to TypeScript, but I've encountered some challenges getting everything to function correctly. import React from "react"; import * as ReactDOM from "react-dom"; import Applicatio ...

The values of the data members remain static within the Typescript environment

In my Ionic 2 project, I have a class structured like the one below. Instead of using the Ionic Native geolocation plugin, I am working with the locationServices plugin. export class LocationManager{ locationAcquiring:boolean; locationAvailable:b ...

The Context API's `useContext` hook appears to be malfunctioning, persistently

My situation is as follows: export const LocationContext = createContext(null); export const LocationProvider = LocationContext.Provider; export const useLocationContext = () => useContext(LocationContext); Using the Provider: export const Search = () ...

Developing Angular2 applications in Visual Studio Team Services (formerly known as Visual Studio Online)

Currently, I have an angular2 client integrated into a Visual Studio vNext (ASP.Net 5) project. During my attempt to create a build in Visual Studio Team Services, I encountered errors similar to this one during the build step: It appears that module &a ...

Issue: Unable to locate a matching object '[object Object]' of type 'object'. NgFor can solely bind to data structures like Arrays and Iterables

I am facing an error that says "Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays." I am trying to create a Notification list but I can't figure out w ...

When onSubmit is triggered, FormData is accessible. But when trying to pass it to the server action, it sometimes ends up as null

I am currently utilizing NextJS version 14 along with Supabase. Within my codebase, I have a reusable component that I frequently utilize: import { useState } from 'react'; interface MyInputProps { label: string; name: string; value: stri ...