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 / flip.ts
Last active May 18, 2022 21:00
Flip a Map in TypeScript (with literal types)
/**
* @example
*
* const map = new Map([
* ['a', 3],
* ['b', 1],
* ['c', 15],
* ['d', 3],
* ] as const);
*
@karol-majewski
karol-majewski / SortedArray.ts
Last active July 7, 2020 16:17
Subclassing built-in JavaScript (objects such as Array) in TypeScript
type Comparator<T> = (left: T, right: T) => Comparison;
enum Comparison {
LessThan = -1,
Equal = 0,
GreaterThan = 1,
}
/**
* We can't allow sorted arrays to be mutated (e.g. pushed to).
@karol-majewski
karol-majewski / global.d.ts
Created July 7, 2020 14:11
Make Array.prototype.every act as a type guard in TypeScript
declare global {
interface Array<T> {
every<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): this is S[];
}
}
export {}
@karol-majewski
karol-majewski / match-media.md
Created July 6, 2020 08:38
The most complex type I've ever written

Context

I have a MatchMedia component that renders content based on the current media query.

<MatchMedia between={['sm', 'md']}>
  "I will be shown on small to medium devices"
</MatchMedia>
@karol-majewski
karol-majewski / zip-heterogeneous.ts
Last active July 3, 2020 14:16
Type-safe zipping with TypeScript
declare function zip<T extends readonly unknown[] | [unknown], U extends readonly unknown[] | [unknown]>(
left: T,
right: U & { length: T['length'] }): {
[K in keyof T & keyof U]: [T[K], U[K]]
}
zip([1, 2], ['one', 'two']);
zip([1, 2] as const, ['one', 'two'] as const);
zip([1, 2, 3], ['one', 'two']); // Compile-time error
@karol-majewski
karol-majewski / is-palindrome.ts
Created July 3, 2020 00:21
The easiest way to check if a string is a palindrome in TypeScript
const isPalindrome = (phrase: string): boolean => {
const original = phrase.toLowerCase().replace(/[^A-Za-z0-9]/g, '');
const reversed = original.split('').reverse().join('');
return original === reversed
}
console.log(
isPalindrome("A man, a plan, a canal – Panama!")
)
@karol-majewski
karol-majewski / stylesheet.ts
Created July 2, 2020 19:47
Re-defining standard library types TypeScript
declare global {
namespace StyleSheet {
interface External extends StyleSheet {
href: string;
}
interface Internal extends StyleSheet {
href: null;
}
}
@karol-majewski
karol-majewski / localhost-window.ts
Created June 24, 2020 11:20
Model Window depending on the environment in TypeScript
enum Hostname {
IPv4 = 'localhost',
IPv4Default = '127.0.0.0/8',
IPv6 = '[::1]',
}
const isLocalhost = (window: Window): window is Window.Localhost => (
window.location.hostname === 'localhost' ||
window.location.hostname === '[::1]' ||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/.test(window.location.hostname)
type Opening = '(' | '{' | '[';
type Closing = ')' | '}' | ']';
type Parenthesis = Opening | Closing;
const parentheses: Record<Opening, Closing> = {
'(': ')',
'[': ']',
'{': '}',
};
@karol-majewski
karol-majewski / safe-type-guards.ts
Last active August 7, 2020 12:33
Type-safe refinements (type guards) in TypeScript (moved to https://github.com/karol-majewski/refinements)
namespace Refinement {
class Hit<T> {
constructor(readonly value: T) {}
}
class Miss {}
type Result<T> = Hit<T> | Miss;
export function hit<T> (value: T) {