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 in TypeSript by Logan
• 2,140 points
14 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
0 votes
0 answers
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 in TypeSript by Logan
• 2,140 points
25 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 in TypeSript by Logan
• 2,140 points
10 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 in Others by narikkadan
• 11,280 points
722 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 in Others by narikkadan
• 11,280 points
464 views
0 votes
0 answers

how to sign bitcoin psbt with ledger?

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

Mar 9 in Blockchain by Soham
• 8,740 points
277 views
0 votes
0 answers

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

I have this  input in my component ...READ MORE

Apr 29 in Other DevOps Questions by Kichu
• 19,040 points
149 views
webinar REGISTER FOR FREE WEBINAR X
Send OTP
REGISTER NOW
webinar_success Thank you for registering Join Edureka Meetup community for 100+ Free Webinars each month JOIN MEETUP GROUP