Skip to content

Instantly share code, notes, and snippets.

@webstrand
webstrand / type-subtraction.ts
Last active April 5, 2019 14:17
Demonstration of Excluding<T> which emulates the subtractive type `object - T`
// Since typescript nominally types string based enums, we emulate
// the subtractive type `object - T` by making all the properties
// T optional and setting their types to a non-exported enum.
//
// The enum name is long and descriptive to help with debugging.
const enum CannotAssignToPropertyFromExcludedObject { ϕ = "ϕ" }
type Excluding<T extends object> = { [P in keyof T]?: CannotAssignToPropertyFromExcludedObject; } & { [prop: string]: any; }
// Note: If some overlap is acceptable, providing that the overlapping property extends T[P], use
// type Excluding<T extends object> = Partial<T> & { [prop: string]: any };
@webstrand
webstrand / types.ts
Last active March 18, 2021 16:32
Miscellaneous Typescript Types
// true only when `T = any`. When `T = unknown`, returns false.
// `(T extends never ? IsAny : IsNotAny)` produces `IsNotAny` for most types other than any.
// but `(never extends never ? IsAny : IsNotAny)` produces `never` and
// `(any extends never ? IsAny : IsNotAny)` produces `IsAny|IsNotAny`.
// So we wrap it in a second conditional to filter it down to a concrete type.
type isAny<T> = (T extends never ? number : string) extends string ? false : true;
// variation on the above, without the double-conditional.
type standardIsAny<T> = 0 extends T & 1 ? true : false;
@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 / runtype.ts
Created May 21, 2019 18:33
Runtime type validation for typescript
/**
* A TypeScript type compatible runtime type-verification system.
*
* Each instance of {@link Runtype} is a complete type-verification system that
* can prove that an _unknown_ type is actually _known_ type. Runtypes can be
* composed via the convenience constructors {@link Union},
* {@link Intersection}, {@link Tuple}, and {@link struct}. Additionally, when
* constructing a new {@link Runtype}, a parent constraint may be specified in
* {@link RuntypeConfig}.
*
@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 / mapping.ts
Last active May 26, 2019 15:52
Update key/value mapping from changes on another key/value mapping.
import {Multimap, ReadonlyMultimap} from "./multimap";
export type NoInfer<T> = T & { [K in keyof T]: T[K] };
function identityProjection<T>(value: any, primary: T) { return primary }
/**
* Project some sequence of values onto a Map using keys generated by
* {@link surrogate}. Values with the same surrogate key will overwrite, with
* the later insertion order overwriting the earlier.
@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 / UnionToIntersection.ts
Last active April 20, 2023 14:04
UnionToIntersection implemented without using intermediate function
type UnionToIntersection<
T,
U = T extends unknown ? { _: { [_ in T & PropertyKey]: never } } : {},
V = keyof U[keyof U],
// We need to remove the primitive we branded T with when we made it a
// property key. However, if the union T contains a branded type already,
// we must avoid stripping those brands off.
X = true extends (T extends PropertyKey ? true : never) ? never : PropertyKey
> = T extends never ? never : V extends X & infer W ? W : V;
@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 / lease-change.pl
Last active November 13, 2022 10:04
dnsmasq dhcp-script hook
#!/usr/bin/perl
use strict;
use warnings;
use v5.22;
use feature qw(signatures);
no warnings qw(experimental::signatures);
# This script will, when called by dnsmasq's dhcp-script hook, create a per-host
# configuration file. The default configuration will instruct dnsmasq to route
# all subdomains (*.hostname.$DOMAIN) to the hosts leased ip address.