Skip to content

Instantly share code, notes, and snippets.

@veevidify
Last active March 20, 2024 21:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save veevidify/e13786587ef1543ee7a60b03c550fea0 to your computer and use it in GitHub Desktop.
Save veevidify/e13786587ef1543ee7a60b03c550fea0 to your computer and use it in GitHub Desktop.
JS/TS snippets
console.clear();
const liftPromiseDelay = <T = unknown>(val: T): Promise<T> => new Promise(res => setTimeout(() => res(val), 2000));
// library
type Result = {};
const complexFetchParseRoutine = async (resourceUri: string): Promise<Result> => {
console.log('==library: ', 'fetch something');
await liftPromiseDelay(resourceUri);
console.log('==library:', 'parse it');
const res = await liftPromiseDelay(resourceUri[0]);
return res;
}
const complexCleanupRoutine = async (resourceUri: string): Promise<Result> => {
console.log('==library: ', 'clean up resource');
return await liftPromiseDelay(resourceUri);
}
async function *generateResultsFromUris(uris: string[]): AsyncGenerator<Result> {
for (const uri of uris) {
yield await complexFetchParseRoutine(uri);
await complexCleanupRoutine(uri);
}
}
// consumer
const main = async () => {
const uris = ['a res a', 'b res b', 'c res c'];
for await (const result of generateResultsFromUris(uris)) {
console.log('==');
console.log('==consumer: ', { result });
console.log('==');
}
}
main();
// ...
performActions = () => {
const partitions = [];
const chunk = 10;
let partitionIndex = 0;
myArray.forEach(( t, i ) => {
if ( ! partitions[partitionIndex] ) {
partitions[partitionIndex] = [];
}
partitions[partitionIndex].push( t );
if (( i + 1 ) % chunk === 0 ) {
partitionIndex = partitionIndex + 1;
}
});
let batch = 1;
partitions[0].map( p => p.loading !== true
? this.props.mappedDispatch( p )
: null
);
if ( partitions.length > 1 ) {
const batchSubmit = setInterval( _ => {
partitions[batch].map( p => p.loading !== true
? this.props.mappedDispatch( p )
: null
);
batch ++;
if ( batch >= partitions.length ) {
clearInterval( batchSubmit );
}
}, 12000 );
}
}
// define a context function
const context = () => {
let c = 0;
// a closure lives within this higherOrder function lexical scope / context
const closure = () => {
c ++;
return c;
}
return closure;
};
// here we initialize the entire scope itself
let inc = context();
let c = inc(); // results 1
let c1 = inc(); // results 2
let inc2 = context();
let c3 = inc2(); // results 1
let c4 = inc2(); // results 2
// explode dot-separated string: value into nested object
// as used in lodash _.set
// dotString = 'aa.bb.cc.dd', value = 'test'
const dotObject = (dotString, value) =>
dotString.split('.').reverse().reduce(
(acc, cur) => ({ [cur]: acc }),
value
);
type MyT = {
u?: string;
}
const filterProps = <T extends Object>(a: T[], prop: keyof T) => {
return a
.filter((item): item is Required<T> => !!item[prop])
.map(item => item[prop]);
}
const myArr: MyT[] = [
{
u: 'a'
},
{
u: undefined
}
];
const filtd = filterProps(myArr, 'u');
const _pipe = x => (...fns) => fns.reduce((acc, f) => f(acc), x);
// usage
_pipe(x)(f1, f2, f3); // x |> f1 |> f2 |> f3
const _compose = (...fns) => fns.reduceRight((agg, f) => (...args) => agg(f(...args)));
// usage
const complexFunc = _compose(f1, f2, f3);
complexFunc(x); // f1 . f2 . f3 $ x
Array.prototype.pick = function(props) { return this.map(entry => props.reduce((mappedEntry, prop) => ({...mappedEntry, [prop]: entry[prop]}), {}) ) }
const _pick = (arr, props) => arr.map(elem => props.reduce((pickedElem, prop) => ({...pickedElem, [prop]: elem[prop]}), {}));
export const toUnixTime = (timeString: string) => {
let unixTime = Date.parse(timeString);
if (unixTime === NaN) unixTime = Date.parse('1970-01-01');
return unixTime;
};
const firstNInts = (n: number) => [...Array(n)].map((_, i) => i);
export const id = <T = any>(x: T) => x;
export const nop = (..._args: any) => {};
export const noTask = new Promise<void>(nop);
export const liftPromise = <T>(resolution: T) => new Promise<T>(r => r(resolution));
export const filterUndef = <T>(x: T | undefined): x is T => x !== undefined;
export const copyArrayObjects = <T>(a: T[]) => a.map(x => ({ ...x }));
export const getFromId = <T extends { id?: string }>(collection: T[], id: string) =>
collection.find(b => b.id === id);
export function pipe(init: any) {
return (...fns: Function[]) => fns.reduce((agg: any, f: Function) => f(agg), init);
}
export function compose<A, B, C>(fn1: (b: B) => C, fn2: (a: A) => B): (a: A) => C;
// eslint-disable-next-line
export function compose<A, B, C, D>(
fn1: (c: C) => D,
fn2: (b: B) => C,
fn3: (a: A) => B,
): (a: A) => D;
export function compose(...fns: Function[]) {
return (args: any[]) => fns.reduceRight((agg, f) => f(agg), args);
}
export const flatMap = <T = any, U = any>(arr: T[], fn: (arg: T) => U[]): U[] =>
arr.reduce((agg, c) => agg.concat([...fn(c)]), [] as U[]);
export const concat = <T = any>(...args: T[][]) => args.reduce((acc, t) => acc.concat(t), []);
export const createLookup = <T extends { id?: string }>(sources: T[]): { [key: string]: T } =>
sources.reduce(
(idLookup, source) =>
source.id
? {
...idLookup,
[source.id]: source,
}
: idLookup,
{},
);
export const explode = (dotString: string, value: any) =>
dotString
.split('.')
.reverse()
.reduce((acc, cur) => ({ [cur]: acc }), value);
export const omit = <T extends GObject>(obj: T) => (...args: (keyof T)[]): Partial<T> =>
Object.keys(obj).reduce(
(strippedObj, key) => (!args.includes(key) ? { ...strippedObj, [key]: obj[key] } : strippedObj),
{} as Partial<T>,
);
export const revStr = (str: string) => str.split('').reduceRight((s, c) => s + c, '');
export const mapTrue = (_: any) => true;
export const mapFalse = (_: any) => false;
const pick = <T, K extends keyof T>(obj: T, ...keys: (K)[]): Pick<T, K> => {
return keys.reduce((pickedObj, k) => keys.includes(k)
? {
...pickedObj,
[k]: pickedObj[k],
}
: pickedObj, {} as Pick<T, K>);
}
// lodash stuffs
declare const isArray: (arr) => arr is unknown[];
declare const isObject: (obj) => obj is object;
type P = number | string | undefined | null | symbol | boolean | bigint;
type GObject = Record<string, unknown>;
const aToO = <T>(arr: T[], kPrefix = ""): Record<string, T> => {
if (!isArray(arr)) {
arr = [arr];
}
return arr.reduce(
(record, val, ind) => ({
...record,
[`${kPrefix === "" ? ind : [kPrefix, ind].join(".")}`]: val,
}),
{}
);
}
const walkSort = (obj: unknown | unknown[]): typeof obj => {
if (isArray(obj)) {
const children = obj.map(v => walkSort(v));
const sortedInds = children
.map((elem, ind) => ({
stringified: JSON.stringify(elem),
ind
}))
.sort((lhs, rhs) => lhs.stringified.localeCompare(rhs.stringified))
.map(({ ind }) => ind);
return sortedInds.map(ind => children[ind]);
} else if (isObject(obj)) {
const children = mapValues(obj, v => walkSort(v));
const sortedKeyEntries = Object.entries(children).sort(([lhsKey, _l], [rhsKey, _r]) => lhsKey.localeCompare(rhsKey));
return Object.fromEntries(sortedKeyEntries);
} else {
return obj;
}
}
const flat = (o: object | P) => {
if (isArray(o)) {
o = aToO(o);
}
if (isObject(o)) {
return Object.keys(o).reduce((flattened, objKey) => {
const child = (o as GObject)[objKey];
if (!isObject(child)) {
return {
...flattened,
[objKey]: child,
};
}
let flatChild = flat(child) as GObject | P;
if (isArray(flatChild)) {
flatChild = aToO(flatChild, objKey);
}
if (isObject(flatChild)) {
return {
...flattened,
...Object.keys(flatChild).reduce((flattenedChild, childKey) => ({
...flattenedChild,
[`${objKey}.${childKey}`]: (flatChild as GObject)[childKey],
}), {} as GObject)
};
} else {
return {
...flattened,
[objKey]: flatChild
}
}
}, {} as GObject);
} else {
return o;
}
}
const maskString = (a: string) => Array(a.length).fill('#').join('');
const maskInt = (i: number) => parseInt(Array(Math.floor(i).toString().length).fill('9').join(''), 10);
const maskNum = (a: number) => {
const intPart = Math.floor(a);
const decPart = parseInt(a.toString().split('.')[1] ?? '0', 10);
const maskedInt = maskInt(intPart);
const maskedDec = parseFloat(`0.${maskInt(decPart)}`);
return maskedInt + maskedDec;
}
type GO = { [k: string]: any };
type Prim = string | null | undefined | number | boolean;
const checkSensitive = (path: string[], sensitiveKeys: string[]) => path.some(p => sensitiveKeys.includes(p));
const recursiveMask = (o: GO | Prim | Array<any>, sensitiveKeys: string[], path: string[] = []): typeof o => {
const isSensitive = checkSensitive(path, sensitiveKeys);
if (typeof o === 'string') {
if (isSensitive) {
return maskString(o);
} else return o;
}
if (typeof o === 'number') {
if (isSensitive) {
return maskNum(o);
} else return o;
}
if (typeof o === 'object') {
if (o === null) return o;
if (Array.isArray(o)) {
return o.map(v => recursiveMask(v, sensitiveKeys, path));
} else {
const maskedEntries = Object.entries(o).map(([key, v]) => [key, recursiveMask(v, sensitiveKeys, [...path, key])]);
return Object.fromEntries(maskedEntries);
}
}
return o;
}
const deepCp = <T>(o: T): T => {
if (typeof o === 'object') {
if (o === null) return o;
if (Array.isArray(o)) {
return o.map(item => deepCp(item)) as T;
}
return Object.fromEntries(Object.entries(o).map(([k, v]) => [k, deepCp(v)])) as T;
}
return o;
}
console.clear();
const errors = {
TYPE_A: {
code: 100,
message: "Error message for A",
},
TYPE_B: {
code: 101,
message: "Error message for B",
}
} as const;
type ErrorType = keyof typeof errors;
type ErrorProperties = typeof errors[ErrorType];
class MyError extends Error {
private _code: number;
constructor(errorType: ErrorType) {
const errorDetails = errors[errorType];
super(errorDetails.message);
this._code = errorDetails.code;
}
get code(): number {
return this._code;
}
}
const invariant = (assertion: boolean, errorType: ErrorType): true | never => {
if (!assertion) {
throw new MyError(errorType);
}
return true;
}
try {
const fallThroughA = true;
const blockedA = false;
console.log("check0");
invariant(fallThroughA, "TYPE_A");
console.log("check1");
invariant(blockedA, "TYPE_A");
console.log("check2");
} catch {}
try {
const fallThroughB = true;
const blockedB = false;
console.log("check0");
invariant(fallThroughB, "TYPE_B");
console.log("check1");
invariant(blockedB, "TYPE_B");
console.log("check2");
} catch {}
class Base extends Object {
public baseProp: string
constructor() {
super();
this.baseProp = 'b';
}
}
class Derived extends Base {
public derivedProp: string
constructor() {
super();
this.derivedProp = 'd';
}
}
const d = new Derived();
const b: Base = d; // covariant assignment Base <- Derived
// compiled
const eb = new Base();
const ed: Derived = eb; // compile error: Property 'derivedProp' is missing
// in type 'Base' but required in type 'Derived'.
type GetStringProp<T> = (instance: T) => string;
const gb: GetStringProp<Base> = baseInstance => baseInstance.baseProp;
const gd: GetStringProp<Derived> = gb; // contravariant assignment GetStringProp<Derived> <- GetStringProp<Base>
// compiled
const resb = gd({ baseProp: 'b', derivedProp: 'd' }); // const gd: (instance: Derived) => string
// const reb: string
console.log(`resb=${resb}`); // resb=b
const egd: GetStringProp<Derived> = arg => arg.derivedProp;
const egb: GetStringProp<Base> = egd; // ??
const resd = egb({ baseProp: 'b' }); // still compiled, type-checked with
// const egb: (instance: Base) => string
// const resd: string
console.log(`resd=${resd}`); // resd=undefined
console.log(resd.length); // Uncaught TypeError: Cannot read property 'length' of undefined
// inferred: Promise<number>
const pass = async () => {
console.log("pass action");
return Promise.resolve(1);
}
// inferred: Promise<number> but always reject
const fail = async () => {
if (Math.random()) {
console.log("!!fail action!!");
throw new Error('rejected promise');
}
return 1;
}
// actual inferred: Promise<Promise<number>[]>
const bundlingActions = async () => {
// need to fetch something to create this bundled actions
await pass();
// mistake 1: seemingly return a list of promises since function async signifies promise
// actually returning promise of list of promises
return [
pass(),
pass(),
fail(),
pass()
];
}
const handler = async () => {
const multiActions = [
pass(),
pass(),
bundlingActions() /// mistake 2: not spreading this since the intention is to await Promise.all
];
try {
await Promise.all(multiActions);
console.log("passed");
} catch (err) {
console.log("we caught the err! pass it to error handler");
// next(err);
}
}
handler();
interface HKT {
input: unknown,
output: unknown,
};
type CallHKT<F extends HKT, I> =
(F & { input: I })["output"];
interface ArrayHKT extends HKT {
output: Array<this["input"]>
};
// Array<number>
type X = CallHKT<ArrayHKT, number>;
// === //
type Narrow<T> =
| (T extends infer U ? U : never)
| Extract<T, number | string | boolean | bigint | symbol | null | undefined | []>
| ([T] extends [[]] ? [] : { [K in keyof T]: Narrow<T[K]> })
const narrow = <X>(x: Narrow<X>): X => {
return x as X;
}
// === //
type A = { kind: "A", a: string };
type B = { kind: "B", b: number };
type C = A | B;
declare const func: <K extends C["kind"]>(k: K) => Extract<C, { kind: K }> // switch (k) etc etc
type NarrowA = Extract<A, C>
type NarrowB = Extract<B, C>
const a = func("A");
const b = func("B");
const c = func("C");
// === //
interface GenericFn {
(...args: any): void
}
function declareInferrableType<T extends Record<string, GenericFn>>(f: T) {
return f;
}
const indexed = declareInferrableType({
'a': () => { },
'b': (n: string) => { },
c: 5,
})
type A = typeof indexed['a']
type B = typeof indexed['b']
// === //
type DeepReadonly<T> =
T extends (infer R)[] ? DeepReadonlyArray<R> :
T extends Function ? T :
T extends object ? DeepReadonlyObject<T> :
T;
type RequireOnly<T, K extends keyof T> = Required<Pick<T, K>> & T;
// === //
// expands object types one level deep
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
// expands object types recursively
type ExpandRecursively<T> = T extends object
? T extends infer O ? { [K in keyof O]: ExpandRecursively<O[K]> } : never
: T;
// === //
const keys = ["a", "b", "c"] as const
type Key = typeof keys[number]
type Shape = {x: string}
type Expected = {a: Shape} | {b: Shape} | {c: Shape}
type MyUnion = {[K in Key]: {[P in K]: Shape}}[Key]
// ^?
// === //
type InpA = { kind: 'a', a: string };
type InpB = { kind: 'b', b: number };
type Inp = InpA | InpB;
type RetA = { retA: number };
type RetB = { retB: string };
type Ret<AB extends Inp> =
AB extends InpA ? RetA :
AB extends InpB ? RetB :
never;
const condRet = <I extends Inp>(cond: I) => {
switch (cond.kind) {
case 'a':
return { retA: 1 } as Ret<I>;
case 'b':
return { retB: '2' } as Ret<I>;
}
}
const r1 = condRet({kind: 'a', a: 'a'});
// ^?
const r2 = condRet({kind: 'b', b: 2});
// ^?
const withTryCatch = <TParams extends unknown[], TResult>(coroutine: (...args: TParams) => Promise<TResult>) => {
const wrappedRoutine = async (...args: TParams): Promise<TResult> => {
try {
const unwrapCoroutineResult = await coroutine(...args);
return unwrapCoroutineResult;
} catch (err) {
// process err
console.log({ err });
throw err;
}
}
return wrappedRoutine;
}
type ApiResponse = {}; type IOResponse = {};
const myCoroutine1 = async (someArg: number, someOtherArg: string): Promise<ApiResponse> => Promise.resolve({});
const myCoroutine2 = async (someArg: boolean, someOtherArg: number): Promise<IOResponse> => Promise.reject(Error('some err'));
class Empty {}
const wrapped1 = withTryCatch(myCoroutine1);
const wrapped2 = withTryCatch(myCoroutine2);
const wrappedInferred = withTryCatch(
async (arg1: object, arg2: string[]) => Promise.resolve(new Empty())
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment