Imagine utilizing an external package named "foo". This package's primary export is an object containing an .extend()
method that enables functionality addition by generating a derived object (while leaving the original untouched). The process typically involves:
import foo from 'foo';
const extendedFoo = foo.extend(
// Custom definition here
);
const result1a = extendedFoo.bar.existingMethod();
const result2a = extendedFoo.bar.addedMethod();
const result1b = foo.bar.existingMethod();
const result2b = foo.bar.addedMethod(); // throws error!
Regrettably, the types provided for this package are lackluster and declare .extend()
to return any
, which proves unhelpful. To address this issue, I can think of a couple of potential solutions:
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 drawback of option 1 lies in the fact that if the original foo
module is referenced elsewhere, TypeScript will wrongly assume it includes this additional method.
On the other hand, option 2 oversimplifies matters and fails to cover all bases: in reality, the Bar
interface is utilized in numerous areas within the type definitions, such as parameter types in functions, part of complex union types, and so forth. Ensuring accuracy across all these scenarios could result in verbose and fragile extended types, whereas with option 1, modification at the source was straightforward.
The ideal resolution would involve revising the provided types - for instance, introducing generics where feasible, starting with the base Foo
type and propagating type parameters accordingly. Assuming a rework of types isn't viable, are there any alternative methods to achieve the desired outcome while circumventing the drawbacks previously mentioned?