Skip to content

Instantly share code, notes, and snippets.

@webbower
Last active October 11, 2024 15:04
Show Gist options
  • Save webbower/ceb11396b28f9906d01a4d88c4f7e466 to your computer and use it in GitHub Desktop.
Save webbower/ceb11396b28f9906d01a4d88c4f7e466 to your computer and use it in GitHub Desktop.
Native JS extensions 😱
function before<A, B, C>(this: (a: A) => B, g: (b: B) => C): (a: A) => C {
const f = this;
return function (x) {
return g(f(x));
// return g.call(this, f.call(this, x));
};
};
function after<A, B, C>(this: (b: B) => C, g: (a: A) => B): (a: A) => C {
const f = this;
return function (x) {
return f(g(x));
// return f.call(this, g.call(this, x));
};
};
interface Function {
before: typeof before;
bfr: typeof before;
after: typeof after;
ftr: typeof after;
}
Function.prototype.before = Function.prototype.bfr = before;
Function.prototype.after = Function.prototype.ftr = after;
const toUpper = (str: string): string => str.toUpperCase();
const len = (x: string): number => x.length;
const double = (x: number): number => x * 2
const isEven = (x: number): boolean => x % 2 === 0;
const myFn = toUpper.bfr(len).before(double).before(isEven);
const myFn2 = isEven.ftr(double).after(len).ftr(toUpper);
/**
* @see https://stackoverflow.com/a/3561711
*/
RegExp.xEscape = function escape(string) {
return string.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&');
};
Function.prototype.xPartial = function partial(...args) {
return this.bind(null, ...args);
};
Object.defineProperties(Number.prototype, {
xDecimal: {
value: function decimal() {
// TODO fix precision @see https://stackoverflow.com/questions/4512306/get-decimal-portion-of-a-number-with-javascript
return Number(this) % 1;
},
configurable: true,
},
});
// isEmpty()
const hasOwnProperty = Object.prototype.hasOwnProperty;
Object.prototype.xIsEmpty = function isEmpty() {
for (let p in this) {
if (hasOwnProperty.call(this, p)) {
return false;
}
}
return true;
};
Boolean.prototype.xIsEmpty = function isEmpty() {
return Boolean(this) === false;
};
Number.prototype.xIsEmpty = function isEmpty() {
return Number.isNaN(this);
};
BigInt.prototype.xIsEmpty = function isEmpty() {
return false;
};
String.prototype.xIsEmpty = function isEmpty() {
return String(this) === '';
};
Array.prototype.xIsEmpty = function isEmpty() {
return this.length === 0;
};
Symbol.prototype.xIsEmpty = function isEmpty() {
return false;
};
RegExp.prototype.xIsEmpty = function isEmpty() {
return false;
};
Promise.prototype.xIsEmpty = function isEmpty() {
return false;
};
Function.prototype.xIsEmpty = function isEmpty() {
return false;
};
Map.prototype.xIsEmpty = function isEmpty() {
return this.size === 0;
};
Set.prototype.xIsEmpty = function isEmpty() {
return this.size === 0;
};
// Map over own props for an object
Object.prototype.xMap = function map(mapFn, thisArg) {
const result = {};
for (const key in this) {
if (Object.hasOwn(this, key)) {
result[key] = mapFn.call(thisArg, this[key], key, this);
}
}
return result;
}
// Time extensions for Number
Object.defineProperties(Number.prototype, {
xSeconds: {
value: function seconds() {
return Number(this) * 1000;
},
configurable: true,
},
xMinutes: {
value: function minutes() {
return this.xSeconds() * 60;
},
configurable: true,
},
xHours: {
value: function hours() {
return this.xMinutes() * 60;
},
configurable: true,
},
xDays: {
value: function days() {
return this.xHours() * 24;
},
configurable: true,
},
xWeeks: {
value: function weeks() {
return this.xDays() * 7;
},
configurable: true,
},
// xMonths: {
// value: function months(monthIndex, isLeapYear = false) {
// if (typeof monthIndex !== 'number' || monthIndex < 0 || monthIndex > 11) {
// throw new TypeError(`Number.xMonths() expects monthIndex to be a number between 0 and 11 inclusive. ${monthIndex} given.`);
// }
// // TODO Add checking for isLeapYear
// const daysInMonth = (
// monthIndex === 1 ? (isLeapYear ? 29 : 28) // February and Leap Year check
// : [3, 5, 8, 10].indcludes(monthIndex) ? 30 // April, June, Sept, Nov are 30-day months
// : 31 // The rest are 31-day months
// );
// return this.days() * daysInMonth;
// },
// configurable: true,
// },
// xYears: {
// value: function years(isLeapYear = false) {
// // TODO Figure out how to account for leap years for more than 1 year
// return this.days() * (isLeapYear ? 366 : 365);
// },
// configurable: true,
// },
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment