Skip to content

Instantly share code, notes, and snippets.

View karol-majewski's full-sized avatar

Karol Majewski karol-majewski

View GitHub Profile
@karol-majewski
karol-majewski / tuple-operations.ts
Created February 29, 2024 16:13
Preserving tuple length
// #region Necessary types
type NonEmptyArray<T> = [head: T, ...T[]];
type Tuple<T> = [T, T];
declare function head<T>(collection: [T, ...T[]]): T;
// #endregion
const cloudflareDNS: NonEmptyArray<string> = ["1.1.1.1"];
const googleDNS: Tuple<string> = ["8.8.8.8", "8.8.4.4"]
// ✅ These Just Work™️
@karol-majewski
karol-majewski / promisify.ts
Created December 29, 2023 13:36
Convert synchronous methods to async methods
type PromisifyMethods<T> = {
[K in keyof T]: T[K] extends AnyFunction ? (...parameters: Parameters<T[K]>) => Promise<ReturnType<T[K]>> : T[K];
};
type AsynchronousStorage = PromisifyMethods<Storage>;
export function promisify(storage: Storage): AsynchronousStorage {
return new Proxy(storage, {
get(target, name: string) {
if (typeof target[name] === 'function') {
import * as React from 'react';
const NON_BREAKING_SPACE_CHARACTER = '\u00A0';
interface Props {
children: string;
/**
* If the text is shorter than this, it will not be processed.
*/
requiredLength?: number;
@karol-majewski
karol-majewski / bound.ts
Last active March 30, 2023 13:12
Decorator that binds class methods compatible with TypeScript 5.0
function bound<This extends object, Args extends any[], Return>(
target: (this: This, ...args: Args) => Return,
context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>
) {
const methodName = String(context.name);
if (context.private) {
throw new Error(`${bound.name} cannot decorate private properties like ${methodName}.`);
}
@karol-majewski
karol-majewski / withValidationState.ts
Created December 20, 2022 16:08
Higher-order adapter for react-aria components used inside Ant Design forms
import React from 'react';
import { Form } from 'antd';
import { ValidationState } from '@react-types/shared';
type PropsAreEqual<P> = (prevProps: Readonly<P>, nextProps: Readonly<P>) => boolean;
/**
* When the wrapped component is placed inside an Ant Design form, this higher-order component
* will grab the validation status from the nearest form field and translate it to `ValidationState`.
*
@karol-majewski
karol-majewski / GenericClassComponent.tsx
Last active December 2, 2022 14:13
The easiest way to use generic Props<T>
import * as React from 'react';
enum Tao { Yin, Yang }
interface Props<T> {
value: T;
onClick(value: T): void;
}
class GenericClassComponent<T> extends React.Component<Props<T>> {
@karol-majewski
karol-majewski / usePrefetch.ts
Last active May 6, 2022 01:23
Easy prefetching with react-query
import { FetchQueryOptions, PayloadType, PrefetchableHook, useQueryClient } from 'react-query';
import { useDeepCompareEffect } from 'react-use';
/**
* Prefetches a query. Cancels any outgoing queries on unmount.
*
* @param hook Hook that returns a `UseQueryResult`.
* @param dependencies List of parameters required to build the key for the hook.
* @param options
*
@karol-majewski
karol-majewski / withProps.ts
Created November 12, 2021 14:47
withProps with support for forwardRef
import * as React from 'react';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function withProps<C extends React.ComponentType<any>, D extends Partial<React.ComponentPropsWithoutRef<C>> & JSX.IntrinsicAttributes>(
Component: C,
defaults: D
): React.ForwardRefExoticComponent<React.PropsWithoutRef<Omit<React.ComponentProps<C>, keyof D>> & React.RefAttributes<React.ElementRef<C>>> {
const renderFunction: React.ForwardRefRenderFunction<React.ElementRef<C>, Omit<React.ComponentProps<C>, keyof D>> = (props, ref) => {
return React.createElement(Component, { ...props, defaults, ref });
};
import React from 'react';
import { autobind } from '@typed-decorators/autobind';
class Rolodex<T> {
index: number;
length: number;
constructor(private sequence: NonEmptyArray<T>) {
this.sequence = sequence;
this.index = 0;
@karol-majewski
karol-majewski / methods-of.ts
Created August 6, 2021 11:54
Extract methods/function properties from a type in TypeScript
type AnyFunction = (...args: any[]) => any;
type FunctionPropertyOf<T> = {
[P in keyof T]: T[P] extends AnyFunction ? P : never;
}[keyof T];
type MethodOf<T> = {
[P in keyof T]: T[P] extends (this: ThisType<T[P]>, ...args: any[]) => any ? P : never;
}[keyof T];