Just adding that if you're trying to add define something that's already declared, then this is the typesafe way of doing so, that also guards against buggy for in
implementations.
export const augment = <U extends (string|symbol), T extends {[key :string] :any}>(
type :new (...args :any[]) => T,
name :U,
value :U extends string ? T[U] : any
) => {
Object.defineProperty(type.prototype, name, {writable:true, enumerable:false, value});
};
Which can be used to safely polyfill. Example
//IE doesn't have NodeList.forEach()
if (!NodeList.prototype.forEach) {
//this errors, we forgot about index & thisArg!
const broken = function(this :NodeList, func :(node :Node, list :NodeList) => void) {
for (const node of this) {
func(node, this);
}
};
augment(NodeList, 'forEach', broken);
//better!
const fixed = function(this :NodeList, func :(node :Node, index :number, list :NodeList) => void, thisArg :any) {
let index = 0;
for (const node of this) {
func.call(thisArg, node, index++, this);
}
};
augment(NodeList, 'forEach', fixed);
}
Unfortunately it can't typecheck your Symbols due to a limitation in current TS, and it won't yell at you if the string doesn't match any definition for some reason, I'll report the bug after seeing if they're already aware.