Skip to content

Instantly share code, notes, and snippets.

View ryangoree's full-sized avatar
🏀

Ryan Goree ryangoree

🏀
View GitHub Profile
@ryangoree
ryangoree / WordMap.ts
Last active April 29, 2024 22:53
A utility type that converts a string of words into a map of values.
/**
* A utility type that returns a union of space-separated words in a string.
*
* @example
* ```ts
* type Foo = Words<'foo bar baz'>;
* // => 'foo' | 'bar' | 'baz'
*/
type Words<TString extends string> =
TString extends `${infer Word} ${infer Rest}` ? Word | Words<Rest> : TString;
@ryangoree
ryangoree / ByIndex.ts
Created February 3, 2024 02:52
ByIndex
/**
* Converts array or tuple `T` to an object with keys as indices and values as element types.
* It's handy for when you need type-safe access based on indices, especially with tuples.
*
* `ByIndex` is useful over `{ [K in keyof T]: T[K] }` for:
* - Keeping index keys as strings for object mapping from tuples.
* - Handling arrays as tuples for a unified index-based object structure.
*
* Example:
* type ExampleTuple = ByIndex<[string, number]>; // { "0": string, "1": number }
@ryangoree
ryangoree / getCallerPath.ts
Last active December 8, 2023 21:26
Attempts to get the path to the file that called the function that called this function.
/**
* Attempts to get the path to the file that called the function that called
* this function.
* @example
*
* #### Caller:
* ```ts
* // /path/to/file.ts
* import { foo } from './path/to/foo.ts';
*
@ryangoree
ryangoree / camelCase.ts
Created November 5, 2023 19:37
Generic hyphen-case to CamelCase util and type
/**
* Converts a hyphenated string to camel case.
*
* @example
* camelCase('foo-bar') // 'fooBar'
*/
export function camelCase<S>(str: S): CamelCase<S> {
return (
typeof str === 'string'
? str.toLowerCase().replace(/-+([^-])/g, (_, c) => c.toUpperCase())
@ryangoree
ryangoree / getOSConfigDir.ts
Last active December 8, 2023 21:24
Get the path to an app specific config directory based on operating system standards
import os from "node:os";
import path from "node:path";
/**
* Get the path to an app specific config directory based on operating system
* standards.
* @param projectName
* @returns
*/
export function getOSConfigDir(projectName: string): string {
@ryangoree
ryangoree / binarySearch.ts
Created September 14, 2023 22:04
Conducts a binary search on a sorted array of items to find the index of a specific target.
/**
* Conducts a binary search on a sorted array of items to find the index of a
* specific target. If the target is not found, it returns the nearest index
* based on the comparator function.
*
* @param items - The sorted array of items to search within.
* @param compare - A comparator function that returns:
* - a negative number if `item` is less than the target,
* - a positive number if `item` is greater than the target,
* - and 0 if `item` is equal to the target.
@ryangoree
ryangoree / DefinedWhen.ts
Last active September 14, 2023 21:55
Experiment for dynamic interfaces
/**
* Construct a type based off T where TDefinedField is defined when
* T matches TDefinedState.
*/
type DefinedWhen<
T extends Record<string, any>,
TDefinedField extends keyof T,
TDefinedState extends Partial<T>,
> =
| (Omit<T, TDefinedField | keyof TDefinedState> &
@ryangoree
ryangoree / convert.ts
Created July 24, 2023 03:14
Deep convert function with converted types
type Converted<T, TOriginal, TNew> = T extends TOriginal
? TNew
: T extends Array<infer U>
? Converted<U, TOriginal, TNew>[]
: T extends object
? { [K in keyof T]: Converted<T[K], TOriginal, TNew> }
: T;
function convert<T, TOriginal, TNew>(
value: T,
@ryangoree
ryangoree / formatBytes.js
Last active March 13, 2023 20:00
formatBytes - Format bytes as human-readable text.
/**
* Format bytes as human-readable text.
* @param {number} bytes Number of bytes.
* @param {number} decimalPlaces Number of decimal places to display.
* @param {number} baseQuantity Number of bytes in a kilobyte.
* @param {string[]} sizes The unites to use for each power of the baseQuantity.
* @return {string} Formatted byte size.
*/
export const formatBytes = (
bytes,
function groupStrings(strings) {
return Object.values(strings.sort().reduce((a, str) => {
const s = str.toLowerCase();
const f = s[0];
a[f] = a[f] ? [...a[f], s] : [s];
return a;
}, {}));
}