簡體   English   中英

如何使用格式化程序函數的可選對象鍵入函數返回類型

[英]How to type function return type with optional object of formatter function

我試圖弄清楚當涉及具有可選格式化程序函數的對象時如何正確鍵入返回值。

對於具有單個值的函數,它工作正常。

type Params = {
    id?: number
    created?: string
}

type FormatFn<TParam extends keyof Params, TValue> = (data: Params[TParam]) => TValue

type Result<TValue> = {
    param: TValue
}

declare function query<TParam extends keyof Params, TValue = Params[TParam]>(
    param: TParam,
    formatter?: FormatFn<TParam, TValue>
): Result<TValue>;

// Works as expected 'created' is type 'Date'
const { param: created } = query('created', (created) => new Date(created || ''))

我想添加一個版本,您可以在其中輸入字符串數組和可選格式化程序函數的對象。

這是我嘗試的游樂場

這將是我的預期輸出:

queries(['id', 'created'], {
    created: (created) => new Date(created || '')
})

// Instead of return type
// {
//     params: {
//         id: number,
//         created: string
//     }
// }
// 
// I want to have this, because of the formatter function
// {
//     params: {
//         id: number,
//         created: Date
//     }
// }
type Params = {
    id?: number
    created?: string
}

type Elem = keyof Params;

type Fn = (value: any) => any

type Predicate<T extends Elem> = Record<T, (value: Required<Params>[T]) => any>

type Reducer<
    Arr extends ReadonlyArray<Elem>,
    Result extends Record<string, any> = {}
    > = Arr extends []
    ? Result
    : Arr extends readonly [infer H, ...infer Tail]
    ? Tail extends ReadonlyArray<Elem>
    ? H extends Elem
    ? Reducer<Tail, Result & Predicate<H>>
    : never
    : never
    : never;

/**
 * Pure js/ts analogy
 */

const reducerPredicate = (elem: string) => ({ [elem]: () => null });

const reducer = <Arr extends string[]>(
    arr: Arr,
    result: { [prop: string]: string } = {}
) => {
    if (arr.length === 0) {
        return result; // 1. end of recursion, this is the last call
    }

    const [head, ...tail] = arr; // 2. from first and before the last

    return reducer(tail, { ...result, ...reducerPredicate(head) });
    // no need for never branch
};

type Result<
    P extends ReadonlyArray<keyof Params>,
    Defaults extends Partial<Record<keyof Params, Fn>>,
    Cache extends P[number] & keyof Defaults = P[number] & keyof Defaults> =
    & { [Prop in Exclude<P[number], Cache>]: Required<Params>[Prop] }
    & { [Prop in keyof Defaults]: Defaults[Prop] extends Fn ? ReturnType<Defaults[Prop]> : never }

function queries<TParams extends Array<keyof Params>, TValues extends Partial<Reducer<TParams>>>(
    params: [...TParams],
    formatter?: TValues
): Result<TParams, TValues> {
    return null as any
}

const multiple = queries(['id', 'created'], {
    created: (created /** string */) => 42,
    id: (value /** number */) => 42
})

操場

在這里,在我的博客中,您可以找到更多解釋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM