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 / 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 });
};
type NonEmptyArray<T> = [T, ...T[]];
const names: NonEmptyArray<string> = ['Sheldon', 'Leonard', 'Penny', 'Rajesh', 'Howard'];
function main(names: NonEmptyArray<string>, n: number){
let index = n - 1;
while (index >= names.length) {
index = Math.floor((index - names.length) / 2);
}
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];
@karol-majewski
karol-majewski / useFunction.ts
Last active July 28, 2021 16:53
Forget about stale closures once for all. Inspired by https://stackoverflow.com/a/67270735/10325032.
/**
* When two functions have the same signature, but are not equal.
*
* Fixes the "'T' could be instantiated with a different subtype of constraint" ts(2322) type error.
*
*/
type WrapperFunction<T extends AnyFunction> = (...parameters: Parameters<T>) => ReturnType<T>;
/**
* Prevents stale closures.
/**
* Returns a `string` if all parts of the created template string are guaranteed to be defined.
* If at least one partial string is nullable, the return value will be null.
*
* @example
*
* ```ts
* safestring`/api/v1/users/${user?.id}`; // string | null
* safestring`/api/v1/users/${"15"}`; // string
* ```
interface Options {
/**
* @default Infinity
*/
maximumAttempts?: number;
/**
* @default 0
*/
timeoutMs?: number
}
@karol-majewski
karol-majewski / logrocket.ts
Last active June 24, 2021 11:39
Using JavaScript Proxies with TypeScript
import LR from 'logrocket';
/**
* Fails silently if `LogRocket#init` throws.
*
* @see https://stackoverflow.com/a/43823282/10325032
*/
export const LogRocket = new Proxy(LR, {
get(target, property: keyof typeof LR, receiver) {
if (property === 'init') {
import React from 'react';
type DeferTypeInference<T> = [T][T extends any ? 0 : never];
interface Props<T extends string> {
themeMap: Record<T, any>
defaultTheme?: DeferTypeInference<T>;
}
class ThemeSwitcherProvider<T extends string> extends React.Component<Props<T>> { }
@karol-majewski
karol-majewski / solver.ts
Last active January 11, 2023 10:32
Filtering string literal types based on an affix in TypeScript
/**
* Challenge: given a list of icon names, find icons that exist in sizes 16x16px *and* 24x24px.
* This is an AND relationship, not an OR relationship.
*
* The solution should be: '16-hamburger' | '16-warning' | '24-hamburger' | '24-warning'.
*/
type IconName =
| '16-hamburger' // 👈🏻
| '16-warning' // 👈🏻
| '16-foo'