[英]How to change the return type of a function based on an optional parameter being provided?
[英]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.