import { FmtString } from './formatting' import { Deunionize, UnionKeys } from './deunionize' export const env = process.env // eslint-disable-next-line @typescript-eslint/ban-types export type Any = {} | undefined | null export type Expand = T extends object ? T extends infer O ? { [K in keyof O]: O[K] } : never : T export type MaybeArray = T | T[] export type MaybePromise = T | Promise export type NonemptyReadonlyArray = readonly [T, ...T[]] // prettier-ignore export type ExclusiveKeys = keyof Omit export function fmtCaption< Extra extends { caption?: string | FmtString } | undefined, >( extra?: Extra ): Extra extends undefined ? undefined : Omit & { caption?: string } export function fmtCaption(extra?: { caption?: string | FmtString }) { if (!extra) return const caption = extra.caption if (!caption || typeof caption === 'string') return extra const { text, entities } = caption return { ...extra, caption: text, ...(entities && { caption_entities: entities, parse_mode: undefined, }), } } export type DistinctKeys = Exclude, keyof T> // prettier-ignore /* eslint-disable-next-line @typescript-eslint/ban-types */ export type KeyedDistinct> = Record & Deunionize, T> // prettier-ignore /* eslint-disable-next-line @typescript-eslint/ban-types */ export type Keyed> = Record & Deunionize, T> /** Construct a generic type guard */ export type Guard = (x: X) => x is Y /** Extract the guarded type from a type guard, defaults to never. */ export type Guarded = // eslint-disable-next-line @typescript-eslint/no-explicit-any F extends (x: any) => x is infer T ? T : never export function* zip(xs: Iterable, ys: Iterable): Iterable { const x = xs[Symbol.iterator]() const y = ys[Symbol.iterator]() let x1 = x.next() let y1 = y.next() while (!x1.done) { yield x1.value if (!y1.done) yield y1.value x1 = x.next() y1 = y.next() } while (!y1.done) { yield y1.value y1 = y.next() } } export function indexed( target: T, indexer: (index: number) => U ) { return new Proxy(target, { get: function (target, prop, receiver) { if ( (typeof prop === 'string' || typeof prop === 'number') && !isNaN(+prop) ) return indexer.call(target, +prop) return Reflect.get(target, prop, receiver) }, }) }