UNPKG

@xlink-network/xlink-sdk

Version:
191 lines (173 loc) 5.21 kB
import { OneOrMore } from "./typeHelpers" export function hasAny<T>(ary: T[]): ary is [T, ...T[]] export function hasAny<T>(ary: readonly T[]): ary is readonly [T, ...T[]] export function hasAny<T>(ary: readonly T[]): ary is readonly [T, ...T[]] { return ary.length > 0 } export function hasLength<T>(input: readonly T[], length: 0): input is [] export function hasLength<T>(input: readonly T[], length: 1): input is [T] export function hasLength<T>(input: readonly T[], length: 2): input is [T, T] export function hasLength<T>(input: readonly T[], length: 3): input is [T, T, T] export function hasLength<T>( input: readonly T[], length: 4, ): input is [T, T, T, T] export function hasLength<T>( input: readonly T[], length: 5, ): input is [T, T, T, T, T] export function hasLength<T>( input: readonly T[], length: number, ): input is OneOrMore<T> { return input.length === length } export function first<T>(ary: readonly [T, ...T[]]): T export function first<T>(ary: readonly [...T[], T]): T export function first<T>(ary: readonly T[]): undefined | T export function first<T>(ary: readonly T[]): undefined | T { return ary[0] } export function last<T>(ary: readonly [T, ...T[]]): T export function last<T>(ary: readonly [...T[], T]): T export function last<T>(ary: readonly T[]): undefined | T export function last<T>(ary: readonly T[]): undefined | T { return ary[ary.length - 1] } const _concat = [].concat export function concat<Ts extends any[]>( ...inputArrays: Ts[] ): Ts[number] extends (infer U)[] ? U[] : never { return _concat.apply([], inputArrays as any) as any } const _reduce = [].reduce export function reduce<Ts extends readonly any[], U>( fn: (acc: U, item: Ts[number], index: number, items: Ts) => U, initialValue: U, inputArray: Ts, ): U { return _reduce.call(inputArray, fn as any, initialValue) as any } export function range(start: number, end: number): number[] { return Array.from({ length: end - start }, (_, i) => i + start) } export function reverse<T>(ary: T[]): T[] { const newAry = [...ary] newAry.reverse() return newAry } export function uniq<T>( ary: T[], iteratee: (item: T) => any = item => item, ): T[] { const seen = new Set<any>() return ary.filter(item => { const key = iteratee(item) if (seen.has(key)) { return false } seen.add(key) return true }) } export function oneOf<T extends string[]>( ...coll: T ): (input: unknown) => input is T[number] export function oneOf<T extends any[]>( ...coll: T ): (input: unknown) => input is T[number] export function oneOf<T extends any[]>( ...coll: T ): (input: unknown) => input is T[number] { return ((input: unknown) => coll.includes(input)) as any } export type SortByIteratee<T> = ( item: T, index: number, ary: T[], ) => number | bigint /** * https://github.com/jashkenas/underscore/blob/1abc36c169947c54c97e266513b1d763d0198f46/modules/sortBy.js */ export function sortBy<T>( iteratee: SortByIteratee<T> | SortByIteratee<T>[], ary: T[], ): T[] { const _iteratee = Array.isArray(iteratee) ? iteratee : [iteratee] return ary .map((value, index, ary) => ({ value: value, index: index, criteria: _iteratee.map(f => f(value, index, ary)), })) .sort((left, right) => compareMultiple(left, right)) .map(v => v.value) } interface CompareMultipleItem<T> { value: T index: number criteria: (number | bigint)[] } /** * https://github.com/lodash/lodash/blob/4.17.15/lodash.js#L4632-L4657 */ function compareMultiple<T>( obj: CompareMultipleItem<T>, oth: CompareMultipleItem<T>, ): number { const objCriteria = obj.criteria const othCriteria = oth.criteria const length = objCriteria.length let index = -1 while (++index < length) { const objCri = objCriteria[index] const othCri = othCriteria[index] let result = 0 if (typeof objCri === typeof othCri) { result = Number((objCri as bigint) - (othCri as bigint)) } else { result = Number(objCri) - Number(othCri) } if (result) return result } return obj.index - oth.index } export interface CurriedMapFindFn { <T, U>(fn: (input: T) => U | undefined, input: readonly T[]): U | undefined <T, U>( fn: (input: T) => U | undefined, ): (input: readonly T[]) => U | undefined } export const mapFind: CurriedMapFindFn = (<T, U>( fn: (input: T) => U | undefined, input: readonly T[], ): U | undefined => { for (const item of input) { const result = fn(item) if (result != null) { return result } } return undefined }) as any export interface CurriedMapFindPFn { <T, U>( fn: (input: T) => Promise<U | undefined> | U | undefined, input: readonly T[], ): Promise<U | undefined> <T, U>( fn: (input: T) => Promise<U | undefined> | U | undefined, ): (input: readonly T[]) => Promise<U | undefined> } export const mapFindP: CurriedMapFindPFn = (async <T, U>( fn: (input: T) => Promise<U | undefined> | U | undefined, input: readonly T[], ): Promise<U | undefined> => { for (const item of input) { const result = await fn(item) if (result != null) { return result } } return undefined }) as any