Skip to content

Instantly share code, notes, and snippets.

@jsamr
Created March 15, 2019 07:57
Show Gist options
  • Save jsamr/1e95b21d9d6f609f320c60ee917ab306 to your computer and use it in GitHub Desktop.
Save jsamr/1e95b21d9d6f609f320c60ee917ab306 to your computer and use it in GitHub Desktop.
// Type definitions for patchinko v4.1.0
// Project: patchinko
// Typescript: 3.1.6
// Definitions by: Jules Samuel Randolph <https://github.com/jsamr>
declare module 'patchinko' {
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends Array<infer U> ? Array<DeepPartial<U>> : T[P] extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : DeepPartial<T[P]>;
}
// Utility types
export type Primitive<T> = T extends number ? number :
T extends string ? string :
T extends boolean ? boolean :
never
// Symbols for unique proxies
export const PSSymbol: unique symbol
export const SSymbol: unique symbol
export const DSymbol: unique symbol
export type PatchInstructionSymbol = typeof PSSymbol | typeof SSymbol | typeof DSymbol
export interface PSPatchInstruction<Q> {
[PSSymbol]: Q
}
export interface DPatchInstruction<Q> {
[DSymbol]: Q
}
export interface SPatchInstruction<Q> {
[SSymbol]: Q
}
/**
* Instructions may be nested.
*/
export type NestedPSPatchInstruction<P> = PSPatchInstruction<P> | PSPatchInstruction<PatchRequest<P>>
export type NestedSPatchInstruction<P> = SPatchInstruction<P> | SPatchInstruction<PatchRequest<P>>
/**
* Instructions returned by patchinko functions.
* Instructions cannot wrap primitives.
*/
export type PatchInstruction<P> = P extends Primitive<P> ? never : NestedPSPatchInstruction<P> | DPatchInstruction<P> | NestedSPatchInstruction<P>
/**
* A full Patch replacement, with no nested instructions.
*/
export type WholesomePatch<M> = {
[P in keyof M]: P extends PatchInstructionSymbol ? never : M[P]
}
/**
* A patch function.
*/
export type PatchFunction<M> = (m: M) => PatchRequest<M>
/**
* A set of patch instructions, nested in hierarchy
*/
export type PatchInstructions<M> = {
[P in keyof M]: P extends PatchInstructionSymbol ? never : M[P] extends Primitive<M[P]> ? M[P] : PatchInstruction<M[P]> | WholesomePatch<M[P]>
}
/**
* A patch request object.
*/
export type PatchRequest<M> = PatchFunction<M> | PatchInstructions<M>
export type P = <M extends object>(m: M, p: PatchRequest<M>, ...pp: PatchRequest<M>[]) => M
export type PS = <M extends object>(p: PatchRequest<M>) => PSPatchInstruction<M>
export type D = <M>() => DPatchInstruction<M>
export type S = <M>(closure: (m: M) => PatchRequest<M>) => SPatchInstruction<M>
export interface Overloaded {
/* P */ <M extends object>(m: M, p: PatchRequest<M>, ...pp: PatchRequest<M>[]): M
/* PS */ <M extends object>(p: PatchRequest<M>): PSPatchInstruction<M>
/* D */ <M>(): DPatchInstruction<M>
/* S */ <M>(closure: (m: M) => PatchRequest<M>): SPatchInstruction<M>
}
export const immutable: Overloaded
export const constant: Overloaded
export const P: P
export const PS: PS
export const D: D
export const S: S
}
declare module 'patchinko/immutable' {
import { immutable } from 'patchinko'
export = immutable
}
declare module 'patchinko/constant' {
import { constant } from 'patchinko'
export = constant
}
declare module 'patchinko/explicit' {
export { P, PS, D, S } from 'patchinko'
}
import { immutable as O } from 'patchinko'
const x = {
foo: { bar: { bish: 'bash' } }
}
const y = {
foo: { bar: { bish: { ahah: 'ouhou' } } }
}
// Correct, wholesome replacement
O(x, { foo: { bar: { bish: 'boo' } } })
// Correct:
O(x, { foo: O({ bar: O({ bish: 'boo' }) }) })
O(y, { foo: O({ bar: O({ bish: { ahah: 'hehe' } }) }) })
// Correct, callback (S)
O(x, { foo: O((m: any) => m) })
// Also correct - but `bar` will not be patched - instead it will be replaced:
O(x, { foo: O({ bar: { bish: 'boo' } }) })
O(y, { foo: O({ bar: O({ bish: O({ ahah: 'hehe' }) }) }) })
// Incorrect - we can't patch `bar` because its container - `foo` is a wholesale replacement:
O(x, { foo: { bar: O({ bish: 'boo' }) } })
// Incorrect - wrapping is only necessary for child structures - patch arguments will always patch, not replace:
O(x, O({ foo: O({ bar: O({ bish: 'boo' }) }) }))
// Incorrect - primitive values cannot be patched:
O(x, { foo: O({ bar: O({ bish: O('boo') }) }) })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment