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 / property-binding-order.ts
Created September 8, 2020 16:38
Property binding order in JavaScript classes (what TypeScript will not save you from)
class Foo {
options = {
ns: this.namespaces
};
constructor(namespaces = []) {
this.namespaces = namespaces;
}
}
interface Milestone {
label: string;
count: number;
}
interface Options {
separator?: string;
}
const format = (milestones: Milestone[], options: Options = { separator: ' ' }): string =>
@karol-majewski
karol-majewski / 0. What are type guards.ts
Last active September 18, 2021 13:14
Snippets used in my talk “Who Guards the Type Guards?” (https://www.youtube.com/watch?v=StyKp5dgN_Y)
/**
* A.K.A. type guard
*/
type Refinement<T, U extends T> = (candidate: T) => candidate is U;
function isString(candidate: unknown): candidate is string {
return typeof candidate === 'string';
}
@karol-majewski
karol-majewski / retry.ts
Created July 25, 2020 22:43
Retry a Promise in TypeScript
const retry = (maxAttemps: number) => <T>(thunk: () => Promise<T>): () => Promise<T> => {
let attempts = 0;
const attempt = async (): Promise<T> => {
attempts++;
let result: T;
try {
result = await thunk();
} catch(error) {
@karol-majewski
karol-majewski / pick-by-value.ts
Created July 21, 2020 18:40
Pick properties from a TypeScript type by their value
interface Dog {
name: string;
bark(): void;
}
declare global {
namespace Pick {
type ByValue<T, U> = Pick<T, PropertyOfValue<T, U>>
}
}
class Node {
next: Node | null = null;
constructor(readonly data: number) {}
}
class LinkedList {
head: Node | null = null;
append(data: number): void {
@karol-majewski
karol-majewski / Serializable.ts
Created July 19, 2020 12:44
JSONLike type in TypeScript
type JSONLike =
| { [property: string]: JSONLike }
| readonly JSONLike[]
| string
| number
| boolean
| null;
interface Serializable {
toJSON(): JSONLike;
@karol-majewski
karol-majewski / IdleStateRecognition.tsx
Created July 18, 2020 14:29
Using React Hooks inside class components with TypeScript
import * as React from 'react';
import { useIdle } from 'react-use';
interface Props {
timeoutMs: number;
children: (data: boolean) => React.ReactElement | null;
}
const IdleStateRecognition: React.FunctionComponent<Props> = ({ children, timeoutMs }) => {
const isIdle = useIdle(timeoutMs);
@karol-majewski
karol-majewski / Dictionary.ts
Last active May 18, 2021 11:28
Create an append-only Map in TypeScript
interface Dictionary<K, V> {
forEach(callbackfn: (value: V, key: K, map: Dictionary<K, V>) => void, thisArg?: any): void;
set(key: K, value: V): this;
has<T extends K>(key: T): this is { get(key: T): V } & Dictionary<K, V>;
has(key: K): boolean;
get(key: K): V | undefined;
readonly size: number;
}
interface DictionaryConstructor {
@karol-majewski
karol-majewski / lib.es2015.collection.d.ts
Created July 15, 2020 20:26
Turn Map.prototype.has into a type guard
const inventory = new Map([
['🍊', 3],
['🍌', 1],
['🍏', 15],
] as const);
if (inventory.has('🍊')) {
const oranges: number = inventory.get('🍊');
}