Creating definitions for generic static members within a third-party module

There is a 3rd party module with the following structure:


export class Container{
  
  static async action() { 
     return {...}
  }
  
  constructor(params = {}) {
   // ...
  }
  
  async doSomething(params = {}) {
    // ...
  }
}

I am looking to define this in a `d.ts` file as follows:

declare module 'container' {
   interface ContainerImpl<T>{
      doSomething(params: Partial<T>): Promise<T>
   }
   
   export const Container: {
      new <T>(params: T): ContainerImpl<T>;
      action<T>(): Promise<T>
   }
}

The above definition is close to what I need. I want to make the export generic, so that the TypeScript compiler understands that the static side does not need to explicitly specify `T` for `action(): Promise<T>`. What I am aiming for is a Generic Container `Constructible<T>` where the `new` method offers `ContainerImpl<T>`:


import { Container } from 'container';

type MyObject = {
   value: string
}

class MyContainer extends Container<MyObject>{}

// Compiler assumes return type as Promise<MyObject>
// since we are extending Conatiner<MyObject>
// This is just an example, ignore the use of top-level await.

await MyContainer.action();

// Expects MyObject type in constructor and assumes a 
// `ContainerImpl<MyObject>` is returned from the constructor.

const impl = new MyContainer({value: 'test'}); 

Answer №1

Firstly, there is a typo in the code snippet:

import {Conatiner} from 'container';

The correct spelling should be Container.

Additionally, top-level await cannot be used. You need to wrap it within an async function.


import { Container } from 'container';

type MyObject = {
    value: string
}

class MyContainer extends Container<MyObject>{ }

const foo = async () => {
    await MyContainer.action()
}

const impl = new MyContainer({ value: 'test' });

impl.doSomething // ContainerImpl<MyObject>.doSomething(params: Partial<MyObject>): Promise < MyObject >

type Impl = typeof impl

type Test = ReturnType<Impl['doSomething']> // Promise<MyObject>

You were almost there and your types are functioning correctly as expected.

Answer №2

It appears that it is possible to specify more specific types for static methods within subclasses, even without altering the implementation. However, make sure to update the signature for action():

declare module "box" {
  interface BoxImpl<S> {
    performAction(inputs: Partial<S>): Promise<S>;
  }

  export const Box: {
    new <S>(inputs: S): BoxImpl<S>;
    action(): Promise<unknown>;
  };
}
class MyBox extends Box<MyItem> {
  static action: () => Promise<MyItem>;
}

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

Develop interactive web applications using Typescript

Having difficulty compiling and executing the project correctly in the browser. The "master" branch works fine, but I'm currently working on the "develop" branch. It's a basic web project with one HTML file loading one TS/JS file that includes i ...

A guide on loading modules dynamically using React and Typescript from a server

I am working on a React / Typescript / Webpack / React-Router application that contains some large JS modules. Currently, I have two bundles (common.js and app.js) included on every page, with common.js being a CommonsChunkPlugin bundle. However, there is ...

I haven't encountered any type warnings in the places where I anticipated them

When I define an object like this: const x: { str: string, num: number } = { str: str, num: not_a_num }; I am surprised to find that even though 'not_a_num' is a string and not a number, the compiler does not throw an error. Instead, ...

Angular Material: Enhanced search input with a universal clear button

After searching for a cross-browser search control with a clear button similar to HTML5, I found the solution rendered by Chrome: <input type="search> The code that gave me the most relevant results can be found here. I used the standard sample w ...

Difficulty encountered while managing dropdown functionality in Protractor using TypeScript

I'm encountering some difficulties when it comes to selecting a dropdown in Protractor. Here's the structure of my DOM: https://i.stack.imgur.com/qK8sT.png This is the XPath I'm using to select the dropdown with the value "Yes": //label[ ...

Top method for allowing non-component functions to update Redux state without the need to pass store.dispatch() as a parameter

As I work on my first ReactJS/redux project, I find myself in need of some assistance. I've developed a generic apiFetch<T>(method, params) : Promise<T> function located in api/apiClient.ts. (Although not a React component, it is indirect ...

What is the best way to access the vue3datepicker object in order to manually close the date picker popup user interface?

Enhancement After yoduh's feedback, I made adjustments to the code below. However, vue3datepicker is still undefined. Code has been updated according to yodubs suggestion. I consulted the official vue3datepicker documentation to customize my own Act ...

Ensuring User Authentication in Angular with Firebase: How to Dynamically Hide the Login Link in Navigation Based on User's Login Status

After successfully implementing Angular Firebase email and password registration and login, the next step is to check the user's state in the navigation template. If the user is logged in, I want to hide the login button and register button. I tried s ...

What is the best way to include the number 7 and other lower numbers in an array?

I am facing an issue where I need to retrieve all the months that have passed in 2020, such as January, February, March, April, May, June, July, and August, and store them in an array. After executing the code below, my variable 'month' returns ...

What could be causing the Typescript error when utilizing useContext in combination with React?

I am currently working on creating a Context using useContext with TypeScript. I have encapsulated a function in a separate file named MovieDetailProvider.tsx and included it as a wrapper in my App.tsx file. import { Context, MovieObject } from '../in ...

Unleashing the power of joint queries in Sequelize

Project.data.ts import { DataTypes, Model, CreationOptional, InferCreationAttributes, InferAttributes, BelongsToManyGetAssociationsMixin, BelongsToManySetAssociationsMixin, BelongsToManyAddAssociationsMixin } from 'sequelize'; import sequelize fr ...

The element at index '0' is not defined for the data type 'number | [number, number]'

In my current project, I have a component named ComponentA which has a defined interface. Here is the snippet of the interface: interface A1 { isSingle: true; value: number; } interface A2 { isSingle: false; value: [number, number]; } exp ...

The @angular/fire package is unable to locate the AngularFireModule and AngularFireDatabaseModule modules

I am facing some challenges while trying to integrate Firebase Realtime Database into my Angular project. Specifically, I am encountering difficulties at the initial step of importing AngularFireModule and AngularFireDatabaseModule. To be more specific, I ...

In Typescript, a function that is declared with a type other than 'void' or 'any' is required to have a return value

I'm a beginner in Angular2/Typescript and I am encountering an error while trying to compile my project: An error is showing: A function that has a declared type other than 'void' or 'any' must return a value. Here is the code sn ...

The Google APIs sheet API is throwing an error message stating "Invalid grant: account not found"

I need to retrieve data from a spreadsheet using the Sheet API. After setting up a project in Google Cloud Platform and creating a service account, I granted the account permission to edit the spreadsheet. I then downloaded the credentials in JSON format. ...

Disabling a specific tab in an array of tabs using Angular and Typescript

Displayed below are 5 tabs that can be clicked by the user. My goal is to disable tabs 2 and 3, meaning that the tab names will still be visible but users will not be able to click on them. I attempted to set the tabs to active: false in the TypeScript fi ...

Exploring the attributes of optional features

Dealing with optional properties can be quite tedious. Consider the object test1 in TypeScript: interface Test { a?: { b?: { c?: { d?: string } } }; } const test1: Test = { a: { b: { c: { d: 'e' } } } }; Handling the absence of each proper ...

Having trouble with my React component timer not functioning properly

How can I utilize the Header Component as a Clock timer for my webpage to update every second? Despite searching on Google, I couldn't find examples that match my requirements. Why is the tick() function not functioning properly even though there are ...

Utilizing a Firebase function with Angular

I created the following function: retrieveLikedProperties(): AngularFirestoreCollection<any> { return this.afs.collection('users', ref => ref.where('uid', '==', this._auth.currentUserId) .where(&a ...

Issue with calling function from props in React is not being resolved

There seems to be an issue with the function not being called when passed into a functional component. While the onSubmit function is triggered, the login(email, password) function inside the Login component is never executed. Despite placing console.log s ...