Skip to content

Instantly share code, notes, and snippets.

@cevek
Last active March 7, 2019 11:33
Show Gist options
  • Save cevek/f3823ace147d642a0c04c2bc9e153837 to your computer and use it in GitHub Desktop.
Save cevek/f3823ace147d642a0c04c2bc9e153837 to your computer and use it in GitHub Desktop.
type AtLeastOne<T, U = { [K in keyof T]: { [P in K]: T[P] } }> = { [P in keyof T]?: T[P] } & U[keyof U];
type Exactify<Base, T extends Base> = Base & { [K in keyof T]: K extends keyof Base ? T[K] : never };
declare function requireExact<X extends Exactify<{a: number}, X>>(x: X): void;
type Omit<T, Keys extends string> = Pick<T, Exclude<keyof T, Keys>>;
type IfEquals<X, Y, A=X, B=never> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? A : B;
type WritableKeys<T> = {
[P in keyof T]-?: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, P>
}[keyof T];
type ReadonlyKeys<T> = {
[P in keyof T]-?: IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, never, P>
}[keyof T];
type DateMutableMethods =
| 'setTime'
| 'setMilliseconds'
| 'setUTCMilliseconds'
| 'setSeconds'
| 'setUTCSeconds'
| 'setMinutes'
| 'setUTCMinutes'
| 'setHours'
| 'setUTCHours'
| 'setDate'
| 'setUTCDate'
| 'setMonth'
| 'setUTCMonth'
| 'setFullYear'
| 'setUTCFullYear';
type RDate = { [P in Exclude<keyof Date, DateMutableMethods>]: Date[P] };
interface RArray<T> extends ReadonlyArray<R<T>> {}
interface RMap<K, V> extends ReadonlyMap<R<K>, R<V>> {}
interface RSet<V> extends ReadonlySet<R<V>> {}
interface PPromise<T> extends Promise<R<T>> {}
type Mutable<T> = Mut<T> & T | T;
type Mut<T> = { __brand: Mut<T>; value: T };
type R<T> = T extends Array<infer R>
? RArray<R>
: T extends Map<infer K, infer V>
? RMap<K, V>
: T extends Set<infer V>
? RSet<V>
: T extends Date
? RDate
: T extends Promise<infer P>
? PPromise<P>
: T extends EventTarget
? T
: T extends Error
? T
: T extends Mut<infer R>
? R
: T extends (...args: infer Arg) => infer Ret
? (...args: Arg) => R<Ret>
: T extends object ? { readonly [P in keyof T]: R<T[P]> } : T;
type RetType<T> = T extends (...args: any[]) => infer R ? R : any;
type Args<T> = T extends (...args: infer A) => infer R ? A : any;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment