/* * Actyx SDK: Functions for writing distributed apps * deployed on peer-to-peer networks, without any servers. * * Copyright (C) 2021 Actyx AG */ /* eslint-disable @typescript-eslint/no-explicit-any */ /** * Base type for a tagged union with type as the tag field */ export type Tagged = { readonly type: string } /** * Extract a case from a tagged union based on the (singleton) type of the tag */ export type SelectTag = T extends { type: Tag } ? T : never /** * Type transform that makes a nested type partial, while * leaving alone arrays, readonly arrays, functions and scalars */ /* eslint-disable @typescript-eslint/ban-types */ export type DeepPartial = T extends ReadonlyArray ? T : T extends Function ? T : T extends object ? { [K in keyof T]?: DeepPartial } : T /* eslint-enable @typescript-eslint/ban-types */ export const todo: (...args: any[]) => never = () => { throw new Error('not implemented yet') } export const none: () => never = () => { throw new Error('there should have been something') } /** * Assert that from the type information, a piece of code can never be reached. * If it’s still reached at runtime, this throws an Error. * @public */ export const unreachable: (x?: never) => never = () => { throw new Error('Unreachable code!') } /** * Assert that from the type information, a certain statement can never be reached, * while installing a default value to return in case the type information was wrong * and the statement was in fact reached. * @public */ export function unreachableOrElse(_: never, t: T): T { return t } /** * Avoids lint false positives like "Expression is always false. (strict-type-predicates)" */ export const lookup = (m: { [k: string]: V }, k: string): V | undefined => m[k] /** * Helpers for dealing with "type X = { [ key: K]: Y | undefined } */ type RecordKey = string | number | symbol export type RWPartialRecord = { [P in K]?: V } export type PartialRecord = Readonly> export type PartialRecord2 = { readonly [P in K1]?: { readonly [T in K2]?: V } } export type RWKeyValueMap = RWPartialRecord export type KeyValueMap = PartialRecord export const isDefined = (v: T): v is Exclude => v !== undefined export const valuesOf = (m: PartialRecord): Exclude[] => Object.values(m).filter(isDefined) export const keysOf = (m: PartialRecord): Extract[] => Object.keys(m) as any as Extract[] export const entriesOf = ( obj: PartialRecord, ): [Extract, V][] => Object.entries(obj).filter(([, x]) => isDefined(x)) as any as [Extract, V][] export const entriesOf2 = ( m1: PartialRecord2, ): ReadonlyArray<[Extract, Extract, V]> => entriesOf(m1).reduce, Extract, V]>>( (acc, [k1, m2]) => acc.concat( entriesOf(m2).map(([k2, v]): [Extract, Extract, V] => [ k1, k2, v, ]), ), [], ) export const toKeyValueMapF = ( getKey: (v: T) => string, map: (v: T) => U, xs: ReadonlyArray, ): KeyValueMap => xs.reduce>((acc, v) => { acc[getKey(v)] = map(v) return acc }, {}) export const toKeyValueMap = (key: K, xs: ReadonlyArray): KeyValueMap => xs.reduce((acc: any, v) => { acc[v[key]] = v return acc }, {}) export const tuple = (...data: T) => data export const PartialRecord = { get(m: PartialRecord, key: K): PartialRecord[K] { return m[key] }, } export const noop = () => undefined