Combining Interface Declarations in TypeScript that Utilize the Same Global Property: A Guide

In my typescript project, I am utilizing multiple cordova plugins. Each plugin is initialized on a global plugins object as shown below:

// Plugin A init
window.plugins.pluginA = {...};

// Plugin B init
window.plugins.pluginB = {...};

However, I am facing an issue regarding how to structure the types so that each plugin can extend the plugins object without being aware of other plugins. The problem arises when defining the type for the second plugin, as it throws an error due to the plugins object already being defined. How should I organize it to allow for extension instead?

// Type declarations for Plugin A
interface IPluginA {
    methodA: (foo: number) => void
}
interface Window {
    plugins: {
        pluginA: IPluginA;
    };
}

// Type declarations for Plugin B
interface IPluginB {
    methodB: (bar: string) => void
}
interface Window {
    // ERROR: Subsequent property declarations must have the same type.
    //     Property 'plugins' must be of type '{pluginA: IPluginA};'
    plugins: {
        pluginB: IPluginB;
    };
}

Answer №1

It seems like you want to combine types that share a common structure - the plugins property. To achieve this, we can use a union type declaration like type Union = A | B.

In your specific example:

// Define specific plugin types
type IPluginA = {
    methodA: (foo: number) => void
}
type IPluginB = {
    methodB: (bar: string) => void
}

// Define WindowA and WindowB with plugins property
type WindowA = {
  plugins: {
      pluginA?: IPluginA
    }
}

type WindowB = {
  plugins: {
      pluginB?: IPluginB
    }
}

// Create MyWindow as a union of WindowA and WindowB
type MyWindow = WindowA | WindowB;

// Initialize win variable with both plugin fields
const win: MyWindow = {
  plugins: {
    // pluginA and pluginB as possible fields
  }
}

If new plugins are added in the future, they can be included in the MyWindow type declaration. Additionally, note that the fields are optional to account for scenarios where not all plugins may be present.

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

Guide on establishing a connection between two MongoDB collections, utilizing TypeScript

'm currently working on establishing a connection between the user and contestant collections. My goal is to retrieve contestants that have been created by a specific user, identified by their user id. And I'm implementing this in typescript. us ...

Guide on making an "enumerable" wrapper for accessors in TypeScript

I've been exploring a method to create an @enumerable decorator that can expose properties set through accessor methods. It's quite simple to achieve this for instances of a class: // This function works well when called in the class constructor ...

Disabling dates in Kendo Date Time Picker (Angular): An easy guide

<input id="startDate" kendo-date-time-picker k-ng-model="vm.startDate" k-on-change="vm.updateStartDate()" required /> Can someone please explain how to incorporate disabled dates into this date picker without utilizi ...

Encountering dual TypeErrors while attempting to implement a login form with ReactiveFormsModule

Using Angular 11, I am facing an issue while creating a login form with ReactiveFormsModule. Upon loading the login page, a TypeError is displayed in the browser console. Additionally, after typing something in the input field, another TypeError appears. h ...

Is there a way to determine the height of the ion-footer?

Is there a way to obtain the height of the ion-footer element in Ionic2? I want to calculate the initial window height minus the ion-footer height, but I am currently only able to get the overall window height. I'm not interested in retrieving the ...

Arranging the properties of an object following the reduction process

I am currently working on replicating the functionality of an Outlook mailbox by organizing a list of Outlook emails based on their conversation ID. However, I am facing the challenge of needing to sort my list twice - once to order the emails in each grou ...

Creating a new object in Typescript with properties that are a subset of another object's properties, determined by an array

The title I wrote might be a bit complicated, so let me clarify my intentions below. Imagine I have a specific type for a document that contains some data: type Doc<TData extends {}> = { data: TData; } In addition, there is a function where I can ...

Is there a way to retrieve keys of the object from this combination type?

Can someone please help me understand how to retrieve keys from this union type? The Value is currently being assigned as a never type. I would like the Value to be either sno, key, or id type Key = { sno: number } | { key: number } | { id: number }; typ ...

Encountered an issue with ionViewDidLoad: The property 'firstChild' cannot be read as it is null

While working on an Ionic 2 App with Angular2 and Typescript, I encountered an issue when trying to pass a JSON to map for markers. Here is the link to the gist containing the code snippet I am facing an error that reads: view-controller.js:231 MapPage i ...

Angular2 tutorial with VS2015 may encounter a call-signature error that is expected

Currently following the Angular2 tutorial in VS2015 and encountering an issue with a warning that is impeding the compilation of one of my TypeScript files. The link to the tutorial is provided below. https://angular.io/docs/ts/latest/tutorial/toh-pt4.htm ...

Performing a simulated form submission using Angular HttpClient and then redirecting the user after

My current issue involves performing a form POST to a 3rd party payment provider using Angular TypeScript and then redirecting to their hosted payment page. When I submit a standard form via a regular HTML page, the redirection happens automatically. Howev ...

Angular 2 Date Input failing to bind to date input value

Having an issue with setting up a form as the Date input in my HTML is not binding to the object's date value, even though I am using [(ngModel)] Here is the HTML code snippet: <input type='date' #myDate [(ngModel)]='demoUser.date& ...

What is the meaning of '=>' in typescript/javascript?

I keep coming across lots of '=>' in the code I found on the internet. Could someone please explain it to me as if I were 5 years old? (I'm searching for the specific code, and I'll share it here once I locate it).. Found it: ...

Why is it that the component passed in props fails to function properly when invoked as a function? React is signaling a shift in the order of Hooks being called

Here is a simple example I've prepared to illustrate how I am passing a component and then calling it like a function, as well as another example where it works just by calling it normally. You can switch between the working and not working examples b ...

Is the Offset in Node.js FS Out of Bounds, Yet Within Bounds?

Seeking assistance with my Node.js file reading code that's causing an out of range error on the offset, even though it should be within the allowed limits. Any suggestions on how to fix this issue? Code snippet: let offset = 0; let length = ...

What is the method for reaching a static member of a class within a decorator for a method of the same class?

Upon the release of TypeScript 5.0, the new decorator APIs have been introduced and I am eager to utilize them for automatically providing parameters to a method from a static property within the same class. The decorator parameters and factory are defined ...

Implementing Typescript for React Navigation: Configuring navigationOptions effectively

Within a React Native app utilizing React Navigation, I am working on a screen component where I aim to set the title based on given parameters using the navigationOptions property like so: static navigationOptions = ({navigation}) => ({ title: nav ...

What is the purpose of using the spread operator in TypeScript's map method?

return items.map(item => ({ ...item, score: Math.round((item.rate / 100) * 5) })); While this code snippet changes the score value for each object in items, you might be wondering about the use of ...item. What advantage does it provid ...

The browser appears to be interpreting the JavaScript file as HTML, resulting in the error message "Uncaught SyntaxError: Unexpected token '<'"

Referencing a similar unresolved question here: Browser seems to read react JS file as HTML, not JSX I am currently working on a project that is developed with Next.js, React, and Typescript. However, I am facing an issue while trying to integrate a Java ...

Typescript filtering function that results in an empty array

Struggling with filtering an array in typescript and aurelia as I keep getting empty lists. For example, when searching for the keyword ra within the firstName property, I expect to retrieve the object with the name "Raja". Not sure where I'm going w ...