Skip to content

Instantly share code, notes, and snippets.

@webstrand
webstrand / bind.ts
Created July 12, 2019 16:25
Partial Application for any number of arguments
// Find the first item of a list.
export type Head<List extends readonly unknown[]> =
0 extends keyof List ? List[0] : never;
// Find the last item of a list.
export type Last<List extends readonly unknown[]> =
List["length"] extends 0 ? never
: List extends [] ? never
: number extends List["length"] ? List[1e+309]
: List[Tail<List>["length"]];
@webstrand
webstrand / multimap.ts
Last active August 6, 2019 15:13
Implementation of a Multimap type, similar to Map, but each key can have multiple values.
export interface Multimap<K, V> extends Map<K, V> {
clear(): void;
delete(key: K): boolean;
delete(key: K, value: V): boolean;
forEach(callbackfn: (value: V, key: K, map: this) => void, thisArg?: any): void;
get(key: K): V | undefined;
get(key: K, value: V): V | undefined;
getAll(key: K): Set<V> | undefined;
has(key: K): boolean;
has(key: K, value: V): boolean;
@webstrand
webstrand / emitter.ts
Last active August 18, 2019 19:02
Subscribable value emitter
type Bind1<T> = T extends (this: unknown, ...args: infer V) => infer W ? (...args: V) => W : T extends (this: infer U, ...args: infer V) => infer W ? (this: U, ...args: V) => W : never;
export type EmitterParameters<T extends Emitter<any>> = T extends Emitter<infer U> ? Parameters<U> : [];
export interface EmitterEmittable<F extends (...args: any[]) => any, E extends (...args: any[]) => any = F> {
/*
* Emit the {@link values}.
*
* @param defaultContext Default context to bind each function's `this`.
* @param values Values to emit.
@webstrand
webstrand / prefixes.ts
Created September 4, 2019 21:47
Find all of the prefixes of some function type by recursive function
/**
* Unshift T onto the arguments list of S.
*/
type Unshift<S extends (...args: any[]) => any, T> =
S extends (...args: infer U) => any ? (arg: T, ...args: U) => any : never;
/**
* Generate all the prefixes of T, not including
* the nullary function nor T itself (unless T variadic).
* Return types are not preserved.
@webstrand
webstrand / maptree.ts
Created March 29, 2019 16:06
Finitely recursive map types using arrays of values as keys. !!FRAGILE!! Don't use any[] for key type, expect heisenbugs.
export type MapTree<K extends readonly [unknown, ...unknown[]], V> = {
0: Map<K[number], V>,
1: ((..._: K) => any) extends ((_: infer Head, ...__: infer Tail) => any)
? Tail extends readonly [unknown, ...unknown[]]
? Map<Head, MapTree<Tail, V>>
: never
: never
}[K extends readonly [unknown] ? 0 : 1] & {
setKey(key: Readonly<K>, value: V): void;
getKey(key: Readonly<K>): V | undefined;
@webstrand
webstrand / sipe.pl
Created November 7, 2019 17:57
A `cat`-like program which exits when STDOUT is closed. Useful for piping files followed by stdin: `sipe some_file /dev/stdin | your-program`
#!/usr/bin/perl
use strict;
use warnings;
use v5.26;
use Errno qw(EAGAIN EWOULDBLOCK EINTR);
use Fcntl qw(O_WRONLY);
STDOUT->autoflush(1);
# This is a tool like cat, except that it watches for STDOUT close and exits
# immediately.
@webstrand
webstrand / stdin_quine.pl
Last active November 12, 2019 14:51
A self-installing quine that can be piped to a perl binary over the network. Installs to /payload when running from STDIN, keeps STDIN open for interactivity.
#!/usr/bin/perl
BEGIN{B:{$_=<<'STRAP'; chomp; exit (eval() // exit print STDERR $@)}}
#line 4 "STDIN"
my $payload = "/tmp/payload";
last unless $0 eq "-";
my $F; do { local $^F=9999; open($F, '>', $payload) or die "$payload: $!" };
$payload //= "/proc/self/fd/" . fileno($F);
chmod(0744, $F) or die "$payload: $!";
$/="\n__END__\n";
print $F <<EVAL, scalar <STDIN> or die "$payload: $!";
@webstrand
webstrand / append.ts
Last active February 26, 2020 23:52
Three versions of non-recursive Append<T extends unknown[], U> (AppendV3 is recommended)
export type AppendV1<Tuple extends unknown[], Last> =
Tuple extends [infer _1] ? [_1, Last] :
Tuple extends [infer _1, infer _2] ? [_1, _2, Last] :
Tuple extends [infer _1, infer _2, infer _3] ? [_1, _2, _3, Last] :
Tuple extends [infer _1, infer _2, infer _3, infer _4] ? [_1, _2, _3, _4, Last] :
Tuple extends [infer _1, infer _2, infer _3, infer _4, infer _5] ? [_1, _2, _3, _4, _5, Last] :
Tuple extends [infer _1, infer _2, infer _3, infer _4, infer _5, infer _6] ? [_1, _2, _3, _4, _5, _6, Last] :
Tuple extends [infer _1, infer _2, infer _3, infer _4, infer _5, infer _6, infer _7] ? [_1, _2, _3, _4, _5, _6, _7, Last] :
Tuple extends [infer _1, infer _2, infer _3, infer _4, infer _5, infer _6, infer _7, infer _8] ? [_1, _2, _3, _4, _5, _6, _7, _8, Last] :
Tuple extends [infer _1, infer _2, infer _3, infer _4, infer _5, infer _6, infer _7, infer _8, infer _9] ? [_1, _2, _3, _4, _5, _6, _7, _8, _9, Last] :
@webstrand
webstrand / concat.ts
Created February 27, 2020 14:22
Concat<U extends unknown[], V extends unknown[]>
type Concat<U extends unknown[], V extends unknown[]> = {
0: V,
1: {
0: U,
1: [U[0], V[0]],
2: [U[0], V[0], V[1]],
3: [U[0], V[0], V[1], V[2]],
4: [U[0], V[0], V[1], V[2], V[3]],
5: [U[0], V[0], V[1], V[2], V[3], V[4]],
6: [U[0], V[0], V[1], V[2], V[3], V[4], V[5]],
import alias from "@rollup/plugin-alias";
import commonjs from "@rollup/plugin-commonjs";
import resolve from "@rollup/plugin-node-resolve";
import typescript from "@rollup/plugin-typescript";
import { createFilter } from "@rollup/pluginutils";
import surplusCompiler from "surplus/compiler";
function surplus({ include, exclude, sourceMap = false }) {
const filter = createFilter(include, exclude);