Skip to content

Instantly share code, notes, and snippets.

@tvler
tvler / DeepRequiredNonNullable.ts
Last active January 22, 2020 19:52
Recursively remove all undefined and null types from data structures of arbitrary-depth
type DeepRequiredNonNullable<T> = T extends null | undefined
? never
: (T extends (infer ElementType)[]
? DeepRequiredNonNullable<ElementType>[]
: (T extends Record<string | number, any>
? { [key in keyof T]-?: DeepRequiredNonNullable<T[key]> }
: T));
// Number test
type BadPrimitive = number | null | undefined | string;
@tvler
tvler / ImplicityTypedActionPayloadByActionType.ts
Last active April 22, 2020 00:39
Implicitly type an action payload by an action type
type ActionTypes = 'actionA' | 'actionB' | 'actionC' | 'actionNoPayload';
type ActionPayloads = {
actionA: { payload: number };
actionB: { payload: string };
actionC: { foo: boolean; bar: boolean };
};
type Actions = {
[key in ActionTypes]: {
@tvler
tvler / IntersectionObserverBox.tsx
Last active December 21, 2020 23:24
A type-safe, polymorphic Box to wrap any forwardRef component with an Intersection Observer in React
import { useEffect, useRef } from "react";
/*
* A type-safe, polymorphic Box to wrap any forwardRef component
* with an Intersection Observer. Designed to be used in an
* unknown-length array map setting (infinite feed, etc.).
*
* The `callback` prop is closed over the passed-in `id` prop.
* This allows the `callback` prop to keep reference-equality
* between renders using something like `useCallback`, which
@tvler
tvler / MockedApolloClient.ts
Created January 14, 2021 00:14
A mocked version of ApolloClient for Jest tests
import { ApolloCache, ApolloClient, ApolloLink, NormalizedCacheObject } from '@apollo/client';
class MockedApolloLink extends ApolloLink {
split = jest.fn();
concat = jest.fn();
request = jest.fn();
setOnError = jest.fn();
protected onError = jest.fn();
}
@tvler
tvler / WriteFragment.tsx
Created February 8, 2021 17:49
WriteFragment: A declarative way to write fragments to Apollo cache using React components
import { useApolloClient, Cache } from "@apollo/client";
import { useEffect } from "react";
/*
* WriteFragment: A declarative way to write fragments to Apollo cache
* using React components. When the fragment props change, the cache is
* updated. When then component unmounts, the fragment is deleted.
*
* This is essentially a reactive version of the cache.writeFragment
* method, using the same exact arguments and types.
@tvler
tvler / createNamespacedEnum.ts
Last active June 9, 2021 01:26
A function to create namespaced enums in typescript, where the return type is a literal reflection of the returned enum value itself
/*
* TS Playground: https://www.typescriptlang.org/play?noUncheckedIndexedAccess=true&noUnusedLocals=true&noUnusedParameters=true#code/PQKgUABCEEIKYHMCWA7CcAeBDAtgBwBs5IRgwwBjAexQGcAXdbfIiAXggoCc4t64Acrji08WCnAAmAURQBXHAAoA3pAi049AIIAuCAG0A5FkMAaCIYBGhgLqm1G+jD1GT5q2YsVb9gL4BKAG5yTFxCOAA6Ry0IrAhgYAgAImjYpJDmcKjNGAiKeMSUnLz0sFASCFlJJjCiEjIwADM5FAp6JBpOHj5BYVFxKVkFAB41IRwRMQkmfhRJWnV6LlQEewhK+RwAaTgATxm4OYWGZZRVtSHtvYXMWfmILS4uLF3hy53dgD41iABJFDwckYt0O9wASnBqFxJMNxpMBuZ9BFke9rjZPmBPoo1KhAfQ9P88fZ-HpVOt9Cg+lM4BBUJUMEtxPQPrRhoSgZ8bKS1OTDgoPrS0AAVOThaRECYoehC3Z4OBsgFAilUgborkQAAGABJlJSJv0JL4Ijq+Vddr4NcF1r5gr4IGSIPRZTTLgA1LAEOQ0jja5Rwg1wI061Hmy1qJ1yiAABSwXHaHv91Jkm3YEAhUJhiYRachVGhb02H3Mbo9Xs+n2CamodEYYjjSATKokyYUtD0j2erxj9cb+qTl0+qcUAHlLAArSH0CKHJZIESKXFA-wQLALDsvUbrckAaz2eizEnMADdS3A9CHaDY1J9-BEcFg8IpFMq+9nTSybMu2IOHetqwx0E2Ucx1TZQ7VXHMMwLfk9mLTZ3U9OAKx5CBGjzCBFH-YFCz2CAqEaQCYN2Whl1-LcsMInAEK9c94NPVNfT1eFDWNZR3z2C0VwWEtEKtLd1lNYD9HY3YbFTU1qLgPjrXIfieHoOQuDQZQDCYgN1UE8cIHAhZu3jAgD0GTY+ICSs-xoAC1P7FMOGAydYloWgkAQF
@tvler
tvler / inferTuple.ts
Created March 24, 2021 21:30
Infer an array argument as a tuple in typescript
// TS playground:
// https://www.typescriptlang.org/play?#code/PTAElByAoAzBXA7AxgFwJYHt6lfaBTAJwBVYAHAGzwB5JRQSK9Q8APZPeAEwGdRvkCOAOYBtALoAaUJAB8ACmRlKALlAiAdJoaUxASlABvWqAJ5FBLIsaQAvgG5IiTP2y5C2vETwuAvK-zESnhyIgDkAIahUqEARlGgoYihepCQwABUtOmgABKETOGmfOgAtkzc5KhCABbkAJ58qCWo5IWgcEhomFmgnHjQOKhd8LzI1eHI7eEtoMjo-oSg4bNBWcCpIKCAvBuA1XswCCgYWIQE6AQAjApBqhqa-ILwomJ6hsam5par9o7Okydn5y8vmYBFOFxCEXisShSRSaTAu32nSOILBACYqB55FYVPQgvojHR3rALCtrN8nCM-qCzmigZM-P8CGiIZFonForDdBsEXsOodMKizgBmTFBZhsDg8PgCYTibHXPGMAlvMwkz7khyUlxM4X00CMmkEYWsqEchJcoA
// ✅
function inferTuple<
Tuple extends string[],
>(tuple: [...Tuple]) {
return tuple
};
const inferTupleTest = inferTuple(['a', 'b', 'c'])
@tvler
tvler / shallowEqualWarnInDev.ts
Last active May 20, 2021 12:43
A custom React.memo memoization function that throws an error (in dev) if props change between renders.
/**
* A strict React.memo memoization function, built off
* the one that comes built-in, that throws an error
* (in dev) if props change between renders. Props you
* want to allow can be passed in as arguments.
*
* This "don't allow by default" model makes it so
* further changes to a component don't silently
* undo any memoization optimizations done before.
*
@tvler
tvler / guard.ts
Created June 9, 2021 16:16
A way to test if a Type adheres to a wider Supertype, without widening the initial Type
type Guard<Type extends SuperType, SuperType> = Type;
const tuple = [1, 2, 3] as const;
type Test = Guard<typeof tuple, ReadonlyArray<number>>;
@tvler
tvler / hoc.tsx
Last active November 7, 2021 01:06
A type-safe high-order-component creator that injects a prop named a given string, with a type inferred by a given hook's return value.
/**
* A type-safe high-order-component creator
* that injects a prop named a given string,
* with a type inferred by a given hook's
* return value.
*
* Ex:
* const Component = ({ name }) => {
* return <>Hello {name}</>;
* };