TypeScript Typing the result of an external module s non-mutating extension function

0 votes

Let's say I'm using external package "foo". Its main export is an object which has an .extend() method that can be used to add functionality by creating a derived object (the original is left unchanged). It looks something like this:

import foo from 'foo';

const extendedFoo = foo.extend(
  // Some complex definition
);

const result1a = extendedFoo.bar.existingMethod();
const result2a = extendedFoo.bar.addedMethod();

const result1b = foo.bar.existingMethod();
const result2b = foo.bar.addedMethod();  // error!

Unfortunately the provided types for the package aren't great and .extend() is declared to return any, which is unhelpful. I can see a couple of ways to fix the issue:

Option 1, module augmentation/interface merging:

import foo from 'foo';

declare module 'foo' {
  interface Bar {
    addedMethod(): string;
  }
}

const extendedFoo = foo.extend(
  // ...
) as foo.Foo;

Option 2, interface extension:

import foo from 'foo';

interface ExtendedBar extends foo.Bar {
  addedMethod(): string;
}

interface ExtendedFoo extends foo.Foo {
  bar: ExtendedBar;
}

const extendedFoo = foo.extend(
  // ...
) as ExtendedFoo;

The issue with option 1 is that if the original foo module is used anywhere, TypeScript will think it has this added method when it doesn't.

The issue with option 2 is that it's oversimplified and incomplete: in reality the Bar interface is used in numerous places in the type definitions, e.g. as the type of a parameter in some functions, as part of big union types or other more complex types, etc. Accounting for all these would make my extended types both lengthy and brittle, whereas with option 1 all I had to do was change the relevant part at its source.

Of course the real solution would be for the provided types to be rewritten - for example a bunch of them could be made generic, including the base Foo type, and the type params propagated through. But assuming that isn't an option, is there any other way I can get the desired result while avoiding the issues I mentioned?

Jul 18, 2022 in TypeSript by Logan
• 2,140 points
273 views

No answer to this question. Be the first to respond.

Your answer

Your name to display (optional):
Privacy: Your email address will only be used for sending these notifications.

Related Questions In TypeSript

0 votes
1 answer
0 votes
1 answer

TypeScript TS7015: Element implicitly has an 'any' type because index expression is not of type 'number'

If you want a key/value data structure ...READ MORE

answered Jun 7, 2022 in TypeSript by Nina
• 3,060 points
14,278 views
0 votes
0 answers

What should the return type of Promise.race be? (Typescript)

For example in the code below, what ...READ MORE

Jul 5, 2022 in TypeSript by Logan
• 2,140 points
321 views
0 votes
0 answers

In typescript, why do the | and & operators flip their meaning when used on function types?

In this code, example1 and example2 are confusing me: type F1 = ...READ MORE

Jul 13, 2022 in TypeSript by Logan
• 2,140 points
323 views
0 votes
0 answers

Typescript: Changing the definition of some third party types d.ts

I am a little bit lost how ...READ MORE

Jul 18, 2022 in TypeSript by Logan
• 2,140 points
804 views
0 votes
1 answer

How to set meta tags using Angular universal SSR and ngx-seo plug-in?

first Install the plug-in with npm i ngx-seo ...READ MORE

answered Feb 11, 2022 in Others by narikkadan
• 63,420 points
1,918 views
0 votes
1 answer

How to use next-seo for setting nextjs meta tag with multiple OGP images?

https://github.com/garmeeh/next-seo use this git repo that contains ...READ MORE

answered Feb 24, 2022 in Others by narikkadan
• 63,420 points
5,121 views
0 votes
0 answers

how to sign bitcoin psbt with ledger?

I'm trying to sign a PSBT transaction ...READ MORE

Mar 9, 2022 in Blockchain by Soham
• 9,700 points
1,288 views
0 votes
1 answer

Can't bind to 'ngModel' since it isn't a known property of 'input'

Just add this in the app.module.ts file: import { FormsModule ...READ MORE

answered Apr 30, 2022 in Other DevOps Questions by narikkadan
• 63,420 points
3,936 views
webinar REGISTER FOR FREE WEBINAR X
REGISTER NOW
webinar_success Thank you for registering Join Edureka Meetup community for 100+ Free Webinars each month JOIN MEETUP GROUP