This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
async function wrapRedis<T>(key: string, fn: () => Promise<T>, seconds = 60): Promise<T> { | |
const cached = await redis.get(key); | |
if (cached) return JSON.parse(cached); | |
const recent = await fn(); | |
if (recent) { | |
await redis.set(key, JSON.stringify(recent), 'ex', seconds); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export function useThrottle<T>(value: T, limit = 1000) { | |
const [throttledValue, setThrottledValue] = useState(value); | |
const lastRan = useRef(Date.now()); | |
useEffect(() => { | |
const handler = setTimeout(() => { | |
if (Date.now() - lastRan.current >= limit) { | |
setThrottledValue(value); | |
lastRan.current = Date.now(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* TypeScript currently lacks a way of typing a record of keys only but not values. | |
* we need this because we want an object of typed keys but we want to leave the values inferred. | |
* thankfully, we can do this with generics. This function allows the second generic's values to be inferred | |
* so that our object is fully type safe for hugely complex types, but we can guarantee that all the keys we need exist. | |
* It's not perfect, but it gets the job done for the time being | |
*/ | |
export function ensureKeys<T>() { | |
/** | |
* Function that returns the value that gets put in, values are type-safely inferred |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Handle clicks outside of an element. | |
* This is useful for closing a modal by clicking outside of the modal. | |
* @param callback - The callback function to run when clicking outside of an element | |
*/ | |
export function useOutsideClick<E extends HTMLElement = HTMLElement>(callback: () => unknown) { | |
const container = useRef<E | null>(null); | |
useEffect(() => { | |
const handler = (event: MouseEvent) => { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface Schema<Out> { | |
parse(value: unknown, path: string): Out; | |
} | |
type Resolve<T> = T extends Schema<infer R> ? Resolve<R> : T; | |
function bool(): Schema<boolean> { | |
return { | |
parse(value, path) { | |
const valid = typeof value === "boolean"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {Dialog, Transition} from '@headlessui/react'; | |
import React, {Fragment, ReactNode} from 'react'; | |
import {BiX} from 'react-icons/bi'; | |
interface Props<Y> { | |
isOpen: boolean; | |
close: () => unknown; | |
// Required because used in the callback | |
// eslint-disable-next-line react/no-unused-prop-types |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface Interceptor { | |
condition(i: number): boolean; | |
execute(i: number): void; | |
} | |
abstract class FizzBuzzUtils { | |
protected isMultipleOf(a: number, multiplier: number) { | |
return a % multiplier === 0; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Constructor<T> = new (...args: any[]) => T; | |
type Then<T, R> = (value: T) => R; | |
export function ifInstance<T, R>(instance: Constructor<T>, then: Then<T, R>) { | |
return (value: unknown) => { | |
if (value instanceof instance) { | |
return then(value); | |
} | |
throw value; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Multiplication in raw TypeScript. Please, please do not ever ever ever use this | |
type TupleOfLength< | |
T, | |
L extends number, | |
R extends T[] = [] | |
> = R["length"] extends L ? R : TupleOfLength<T, L, [...R, T]>; | |
type FlattenResult< | |
T extends 0[][], |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type RemoveOn<T extends string> = T extends `on${infer R}` ? R : T; | |
type PropsFor<El extends keyof JSX.IntrinsicElements> = JSX.IntrinsicElements[El]; | |
type OnProps<El extends keyof JSX.IntrinsicElements> = Uncapitalize<RemoveOn<Extract<keyof PropsFor<El>, `on${string}`>>>; | |
type HandlerFor<El extends keyof JSX.IntrinsicElements, Ev extends OnProps<El>> = NonNullable<PropsFor<El>[`on${Capitalize<Ev>}` & keyof PropsFor<El>]>; | |
// Creating with a callback | |
function handlerFor<El extends keyof JSX.IntrinsicElements, Ev extends OnProps<El>>(event: [El, Ev], handler: HandlerFor<El, Ev>) { | |
return handler; | |
} |
NewerOlder