我正在尝试弄清楚当涉及具有可选格式化程序函数的对象时如何正确键入返回值。
对于具有单个值的函数,它工作正常。
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 || ''))
我想添加一个版本,您可以在其中输入字符串数组和可选格式化程序函数的对象。
这是一个Playground我的尝试。
这将是我的预期输出:
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
})
Here ,在我的博客中,您可以找到更多解释。
关于typescript - 如何使用格式化程序函数的可选对象键入函数返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68359417/