Package Exports
- @avstantso/std-ext
- @avstantso/std-ext/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@avstantso/std-ext) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
@avstantso/std-ext
Standard JavaScript objects extension with zero dependencies. Adds useful methods to native String, Array, RegExp, Object, and Symbol with full TypeScript support.
Features
- Zero dependencies
- Full TypeScript support with type inference
- Non-intrusive prototype extensions
- Useful utility methods for common operations
- Type-safe array key types for advanced TypeScript usage
Installation
npm install @avstantso/std-extor
yarn add @avstantso/std-extUsage
Simply import the package once in your application entry point to enable all extensions:
import '@avstantso/std-ext';
// Now all extensions are available
const greeting = "hello".toCapitalized(); // "Hello"
const items = [1, 0, 2, null, 3, false, 4].pack(); // [1, 2, 3, 4]
const escaped = RegExp.escape("file[1].txt"); // "file\\[1\\]\\.txt"API Reference
RegExp Extensions
RegExp.escape(str)
Escapes all RegExp special characters in a string, making it safe to use in new RegExp(). This is a polyfill for the TC39 RegExp.escape proposal.
Parameters:
str: string- The string to escape
Returns: string - New string with escaped RegExp characters
Escaped characters: \ ^ $ . * + ? ( ) [ ] { } |
Example:
RegExp.escape("file[1].txt"); // "file\\[1\\]\\.txt"
RegExp.escape("price: $10.00"); // "price: \\$10\\.00"
RegExp.escape("a+b=c?"); // "a\\+b=c\\?"
// Safe dynamic RegExp creation
const userInput = "test.file[1]";
const regex = new RegExp(RegExp.escape(userInput));
regex.test("test.file[1]"); // true
regex.test("testXfile11"); // falseObject Extensions
Object.definePropertyOnce(o, p, attributes)
Adds a property to an object only if it doesn't already exist. Useful for polyfills and non-intrusive extensions. Especially handy for hot module replacement (HMR) environments like Vite, Webpack, or Parcel where modules may be re-executed multiple times.
Parameters:
o: T- Object on which to add the propertyp: PropertyKey- The property nameattributes: PropertyDescriptor- Descriptor for the property
Returns: T - The object passed in
Example:
const obj = { existing: 1 };
Object.definePropertyOnce(obj, 'existing', { value: 999 });
Object.definePropertyOnce(obj, 'newProp', { value: 2 });
console.log(obj.existing); // 1 (unchanged)
console.log(obj.newProp); // 2 (added)
// Useful for polyfills
Object.definePropertyOnce(String.prototype, 'myMethod', {
value() { return this.toUpperCase(); }
});Object.definePropertiesOnce(o, properties)
Adds multiple properties to an object, skipping any that already exist. Same HMR benefits as definePropertyOnce.
Parameters:
o: T- Object on which to add the propertiesproperties: PropertyDescriptorMap- Object containing property descriptors
Returns: T - The object passed in
Example:
const obj = { a: 1 };
Object.definePropertiesOnce(obj, {
a: { value: 999 }, // skipped - already exists
b: { value: 2 }, // added
c: { value: 3 } // added
});
console.log(obj); // { a: 1, b: 2, c: 3 }Symbol Extensions
Symbol.Has(symb, resultTemplate?)
Creates a type guard function that checks if an object has a specific symbol property. Returns a reusable checker function with proper TypeScript type narrowing.
Parameters:
symb: symbol- The symbol to check forresultTemplate?: R- Optional type-only argument to infer the symbol's value type (not used at runtime)
Returns: (obj: unknown) => obj is { [K in Symb]: R } - Type guard function
Example:
const mySymbol = Symbol('mySymbol');
const hasMySymbol = Symbol.Has(mySymbol);
const obj1 = { [mySymbol]: 'value' };
const obj2 = { foo: 'bar' };
hasMySymbol(obj1); // true
hasMySymbol(obj2); // false
hasMySymbol(null); // false (safe with nullish values)
// Works great with well-known symbols
const hasIterator = Symbol.Has(Symbol.iterator);
hasIterator([]); // true
hasIterator('string'); // true
hasIterator(new Map()); // true
hasIterator({}); // false
// Type narrowing in conditionals
const data: unknown = getExternalData();
if (hasIterator(data)) {
for (const item of data) { ... } // TypeScript knows data is iterable
}
// With typed value using resultTemplate
const symbolFreeze = Symbol('freeze');
const hasFreeze = Symbol.Has(symbolFreeze, () => {});
if (hasFreeze(obj)) {
obj[symbolFreeze](); // TypeScript knows it's () => void
}String Extensions
toCapitalized()
Capitalizes the first character of the string.
Returns: Capitalize<S> where S is the string literal type
Example:
"hello".toCapitalized(); // "Hello"
"world".toCapitalized(); // "World"
"".toCapitalized(); // ""
// Preserves literal types
const a = 'foo' as const;
const b = a.toCapitalized(); // type is 'Foo', not stringtoUncapitalized()
Uncapitalizes the first character of the string.
Returns: Uncapitalize<S> where S is the string literal type
Example:
"Hello".toUncapitalized(); // "hello"
"World".toUncapitalized(); // "world"
"".toUncapitalized(); // ""
// Preserves literal types
const a = 'FOO' as const;
const b = a.toUncapitalized(); // type is 'fOO', not stringArray Extensions
pack()
Filters out all falsy values from the array (false, 0, "", null, undefined, NaN).
Returns: New array with only truthy items
Equivalent to: filter((item) => item)
Example:
[1, 0, 2, null, 3, false, 4].pack(); // [1, 2, 3, 4]
["a", "", "b", null, "c"].pack(); // ["a", "b", "c"]
[true, false, true, undefined].pack(); // [true, true]
// Real world example: React conditional CSS classes
function Button({ isActive, isDisabled, isLoading }) {
return (
<button
className={[
'btn',
isActive && 'btn--active',
isDisabled && 'btn--disabled',
isLoading && 'btn--loading'
].pack().join(' ')}
>
Click me
</button>
);
}
// Compare to the alternative without pack():
function Button({ isActive, isDisabled, isLoading }) {
return (
<button
className={`btn${
isActive ? ' btn--active' : ''
}${
isDisabled ? ' btn--disabled' : ''
}${
isLoading ? ' btn--loading' : ''
}`}
>
Click me
</button>
);
}peek()
Returns the last element of the array without modifying it.
Returns: Last item or undefined if array is empty
Equivalent to: at(-1)
Example:
[1, 2, 3, 4].peek(); // 4
["a", "b", "c"].peek(); // "c"
[].peek(); // undefinedTypeScript Advanced Types
The package exports the AVStantso.Array namespace with advanced utility types for working with arrays:
AVStantso.Array.RW<W, T>
Conditional type that selects between Array<T> or ReadonlyArray<T> based on the writable flag.
Type Parameters:
W extends boolean- If true, returnsArray<T>, otherwiseReadonlyArray<T>T- Array element type (default:unknown)
Example:
type MutableArray = AVStantso.Array.RW<true, number>; // Array<number>
type ImmutableArray = AVStantso.Array.RW<false, string>; // ReadonlyArray<string>AVStantso.Array.Key<W>
Gets all valid array method/property keys based on mutability.
Type Parameters:
W extends boolean- If true, includes mutation methods; if false, only readonly methods
Example:
type ReadonlyKeys = AVStantso.Array.Key<false>; // Keys like 'map', 'filter', 'length'
type MutableKeys = AVStantso.Array.Key<true>; // Includes 'push', 'pop', 'splice'AVStantso.Array.Key namespace
Helper types for array keys:
AVStantso.Array.Key.R- Readonly array keys onlyAVStantso.Array.Key.RW- All array keys (readonly + writable)AVStantso.Array.Key.W- Mutation keys only (writable but not readonly)
Example:
type ReadonlyMethods = AVStantso.Array.Key.R; // 'map', 'filter', 'forEach', etc.
type AllMethods = AVStantso.Array.Key.RW; // All array methods
type MutationOnly = AVStantso.Array.Key.W; // 'push', 'pop', 'splice', etc.Requirements
- Node.js 12.0 or higher
- TypeScript 4.0 or higher (for TypeScript projects)
TypeScript Configuration
To use the type extensions, ensure your tsconfig.json includes the package:
{
"compilerOptions": {
"types": ["@avstantso/std-ext"]
}
}Or simply import it once in your entry file as shown in the Usage section.
License
MIT - See LICENSE file for details
Repository
GitLab - avstantso-js/cross-platform-utils
Contributing
Contributions are welcome! Please feel free to submit issues or pull requests to the repository.