Skip to main content

Define Prototype Method

definePrototypeMethod​

The definePrototypeMethod function safely defines methods on any prototype — including built-in prototypes — in an idempotent manner. The method is non-enumerable by default and will not overwrite existing methods unless explicitly allowed.

Function Signature​

definePrototypeMethod<Proto extends object, Name extends keyof Proto>(
proto: Proto,
name: Name,
impl: (...args: unknown[]) => unknown,
options?: ProtoMethodOptions
): void

Parameters​

ParameterTypeDescription
protoProtoThe target prototype object (e.g., String.prototype)
nameNameThe method name to define on the prototype
implFunctionThe function implementation for the method
optionsProtoMethodOptions (optional)Property descriptor settings and overwrite rules

Options​

interface ProtoMethodOptions {
/**
* - Whether an existing method with the same name should be replaced.
* - Defaults to `false`.
*/
overwrite?: boolean;

/**
* - Whether the method should appear during property enumeration (e.g., in `for...in` or `Object.keys`).
* - Defaults to `false`, matching native prototype method behavior.
*/
enumerable?: boolean;

/**
* - Whether the method's property descriptor can be modified or deleted.
* - Defaults to `false`.
* - When `false`, the method cannot be removed or reconfigured, but its value may still be changed if `writable` is `true`.
*/
configurable?: boolean;

/**
* - Whether the method's value may be reassigned after definition.
* - Defaults to `true` to allow replacement of the function body unless explicitly locked down.
*/
writable?: boolean;
}

Example Usage​

import { definePrototypeMethod } from 'nhb-toolbox';

// Extend TypeScript global interface
declare global {
interface String {
toBang(): string;
}
}

// Define a custom method on String.prototype
definePrototypeMethod(String.prototype, 'toBang', function (this: String) {
return this.toString().concat('!');
// or
// return this.concat('!');
});

"Hello".toBang(); // "Hello!"

// Safe redefinition (ignored without overwrite)
definePrototypeMethod(String.prototype, 'toBang', () => 'x');
"Hello".toBang(); // Still "Hello!"

// Force overwrite
definePrototypeMethod(
String.prototype,
'toBang',
function (this: String) { return this + '!!!'; },
{ overwrite: true }
);

"Hello".toBang(); // "Hello!!!"

Features​

  • Safe by Default: Won't overwrite existing methods without explicit permission
  • Non-enumerable: Methods don't appear in for...in loops by default
  • TypeScript Ready: Works with global interface augmentation
  • Configurable: Fine-grained control over property descriptor

Use Cases​

  • Adding utility methods to built-in prototypes
  • Polyfilling proposed JavaScript features
  • Creating domain-specific language extensions
  • Safe prototype augmentation in libraries

Best Practices​

  • Always declare TypeScript interfaces when extending built-ins
  • Use descriptive method names to avoid conflicts
  • Consider namespace prefixes for library code
  • Document custom methods clearly for team members