-type CloneableData =
- | number
- | string
- | boolean
- | null
- | undefined
- | Date
- | CloneableData[]
- | { [key: string]: CloneableData }
-
-type FormatKey = (key: string) => string
-
-const deepClone = <I extends CloneableData, O extends CloneableData = I>(
- value: I,
- formatKey?: FormatKey,
- refs: Map<I, O> = new Map<I, O>()
-): O => {
- const ref = refs.get(value)
- if (ref !== undefined) {
- return ref
- }
- if (Array.isArray(value)) {
- const clone: CloneableData[] = []
- refs.set(value, clone as O)
- for (let i = 0; i < value.length; i++) {
- clone[i] = deepClone(value[i], formatKey, refs)
- }
- return clone as O
- }
- if (value instanceof Date) {
- return new Date(value.valueOf()) as O
- }
- if (typeof value !== 'object' || value === null) {
- return value as unknown as O
- }
- const clone: Record<string, CloneableData> = {}
- refs.set(value, clone as O)
- for (const key of Object.keys(value)) {
- clone[typeof formatKey === 'function' ? formatKey(key) : key] = deepClone(
- value[key],
- formatKey,
- refs
- )
- }
- return clone as O
+/**
+ * Detects whether the given value is an asynchronous function or not.
+ *
+ * @param fn - Unknown value.
+ * @returns `true` if `fn` was an asynchronous function, otherwise `false`.
+ * @internal
+ */
+export const isAsyncFunction = (fn: unknown): fn is (...args: unknown[]) => Promise<unknown> => {
+ return is(Function, fn) && fn.constructor.name === 'AsyncFunction'