Skip to content

Instantly share code, notes, and snippets.

View joemaffei's full-sized avatar

Joe Maffei joemaffei

View GitHub Profile
@joemaffei
joemaffei / searchParamsToObject.ts
Created January 21, 2025 19:58
Convert searchParams to object
function searchParamsToObject(params: URLSearchParams) {
const uniqueKeys = [...new Set(params.keys())];
return Object.fromEntries(uniqueKeys.map(key => [
key,
params.getAll(key).length > 1 ? params.getAll(key) : params.get(key),
]));
}
@joemaffei
joemaffei / typed-fetch.ts
Created January 13, 2025 18:31
Fetch with typed response, throws on errors
interface TypedResponse<TJson> extends globalThis.Response {
json: () => Promise<TJson>;
}
async function typedFetch<T>(...args: Parameters<typeof fetch>) {
const response = await fetch(...args);
if (!response.ok) throw response;
return response as TypedResponse<T>;
}
@joemaffei
joemaffei / change-screenshots-folder.sh
Created November 26, 2024 00:03
MacOS: change destination folder for screenshots
defaults write com.apple.screencapture location ~/Screenshots/
@joemaffei
joemaffei / leibniz-pi.md
Created November 23, 2024 01:12
Leibniz's formula for Pi using functional programming
const identity = x => x
const withIndex = fn => (_, i) => fn(i);
const getIndex = withIndex(identity);
const positiveIntegers = (length) => Array.from({ length }).map(getIndex);
const isEven = n => n % 2 === 0;
const isOdd = n => !isEven(n);
const odd = (...numbers) => numbers.filter(isOdd);
const reciprocal = n => 1 / n;
const inverse = (...numbers) => numbers.map(reciprocal);
@joemaffei
joemaffei / indexed-object-array.js
Last active November 22, 2024 21:00
Indexed Object Array
class IndexedObjectArray extends Array {
#map;
constructor(length) {
super(length);
}
toMap() {
return this.#map;
}
@joemaffei
joemaffei / squares.ts
Created August 6, 2024 12:33
Sum of Squares
function squares(n: number) {
return (n * (n + 1) * (2 * n + 1)) / 6;
}

Frontend Definition of Done

Curated by Joe Maffei

This document outlines key considerations for determining when a feature can be considered "done." It's crucial to address these points as early as possible in the development process and continue to revisit them at each stage. By doing so, we can ensure higher quality, reduce rework, and streamline our development pipeline. Consider these points at the following stages:

  1. When drafting requirements documents
  2. During the design and wireframing phase
  3. While writing user stories or bug tickets
  4. Throughout the development process
@joemaffei
joemaffei / pickStringKeysAndValues.ts
Last active March 21, 2024 15:03
Convert an iterable to an object, keeping only key/value pairs that are both strings. Useful for excluding File values from FormData.
/**
* Converts an iterable to an object, keeping only key/value pairs that are both strings.
*/
function pickStringKeysAndValues<
T extends { entries(): IterableIterator<[unknown, unknown]> },
>(iterable: T): Record<string, string> {
let result: Record<string, string> = {};
for (let [key, value] of iterable.entries()) {
if (typeof key === 'string' && typeof value === 'string') {
result[key] = value;
@joemaffei
joemaffei / dependency-injection-made-simple.ts
Created March 20, 2024 01:51
Stupid simple dependency injection for TypeScript
/**
* Module-level variable where all of the global dependency injection
* overrides are stored.
*/
const provisions = new Map<unknown, unknown>();
/**
* Adds an override to the global dependency injection context.
* TypeScript ensures that the signature of the override is the same
* as that of the dependency being overridden.
@joemaffei
joemaffei / keyMirror.ts
Created March 11, 2024 23:30
Type-safe key mirror
function keyMirror<Obj>(...args: (keyof Obj)[]): Readonly<{ [Key in keyof Obj]: Key }> {
let obj = {};
for (let arg of args) {
Object.defineProperty(obj, arg, {
configurable: false,
enumerable: true,
value: arg,
writable: false,
});
}