I'm trying to extend the base Array
interface with some custom methods. I looked around SO and typescript docs and finally put together the following code:
// In module Func.ts
declare global {
type Array<T> = {
intersperse(mkT: (ix: number) => T): T[];
};
}
if (!('intersperse' in Array.prototype)) {
Array.prototype.intersperse = function intersperse<T>(this: T[], mkT: (ix: number) => T): T[] {
return this.reduce((acc: T[], d, ix) => [...acc, mkT(ix), d], []).slice(1);
};
}
However, I'm getting the following errors:
// On type Array<T> = { ... }
Duplicate identifier 'Array'.ts(2300)
// On Array.prototype.intersperse = ...
Property 'intersperse' does not exist on type 'any[]'.ts(2339)
Also, whenever I try to use intersperse
in some other file, I get the error
Property 'intersperse' does not exist on type 'Element[]'.ts(2339)
Which is to be expected, considering the declaration in Func.ts
seemingly didn't work. From this I gather that the SO questions are outdated (or incomplete) and that something has changed since.
So, what's the best way to extend to get rid of these errors and extend the Array prototype? Before you say I'm not supposed to do so — yeah, I know all the risks, and I made an informed decision to do it anyway.
Array
is defined as an interface not a type. Interfaces in typescript are open ended and can be added to by multiple declarations. Types do not share the same feature.
export{}
declare global {
interface Array<T> {
intersperse(mkT: (ix: number) => T): T[];
}
}
if (!Array.prototype.intersperse) {
Array.prototype.intersperse = function intersperse<T>(this: T[], mkT: (ix: number) => T): T[] {
return this.reduce((acc: T[], d, ix) => [...acc, mkT(ix), d], []).slice(1);
};
}
As T.J. Crowder mentioned you might consider using Object.defineProperty
to ensure the property is not enumerable:
export {}
declare global {
interface Array<T> {
intersperse(mkT: (ix: number) => T): T[];
}
}
if (!Array.prototype.intersperse) {
Object.defineProperty(Array.prototype, 'intersperse', {
enumerable: false,
writable: false,
configurable: false,
value: function intersperse<T>(this: T[], mkT: (ix: number) => T): T[] {
return this.reduce((acc: T[], d, ix) => [...acc, mkT(ix), d], []).slice(1);
}
});
}