// callbacks
const callback1 = (key: string, value: unknown) => {
if (typeof value !== 'number' || Number.isNaN(value)) throw new Error('error ' + key)
return value
}
const callback2 = (key: string, value: unknown, min: number, max: number = Infinity) => {
if (typeof value !== 'number' || Number.isNaN(value)) throw new Error('error ' + key)
if (value < min || value > max) throw new Error('error')
return value
}
const callback3 = (key: string, value: unknown, something: number) => {
if (typeof value !== 'number' || Number.isNaN(value)) throw new Error('error ' + key)
if (value === something) throw new Error('error')
return value
}
type Obj = { [P: string]: unknown }
const tesstobj: Record<string, unknown> = { one: 1, two: 'two' }
// main
const evaluate = <
O extends Obj,
F extends (key: string, val: unknown) => ReturnType<F> // <--
>(obj: O, prop: keyof O, vfunc: F) => {
if (typeof prop !== 'string') throw new Error('error')
return vfunc(prop, obj[prop])
}
const evaluate_two = <
O extends Obj,
F extends (key: string, val: unknown, ...args: unknown[]) => ReturnType<F> // <--
>(obj: O, prop: keyof O, vfunc: F , ...args: unknown[]) => {
if (typeof prop !== 'string') throw new Error('error')
return vfunc(prop, obj[prop], ...args)
}
evaluate(tesstobj, 'one', callback1) // good
evaluate(tesstobj, 'one', callback2) // error as expected
evaluate_two(tesstobj, 'one', callback2) // ????
在上面的代码片段中,我需要能够将
callback1
/ callback2
/ callback3
传递给 evaluate
的回调参数。我尝试在 evaluate_two
中实现这一目标,但没有成功。
错误信息
Argument of type '(key: string, value: unknown, min: number, max?: number) => number' is not assignable to parameter of type '(key: string, val: unknown, ...args: unknown[]) => number'.
Types of parameters 'min' and 'args' are incompatible.
Type 'unknown' is not assignable to type 'number'.
注意:我知道这可以通过 union 来实现,但它不是动态的,我不喜欢这一点。
您可以传递回调,更新代码
// callbacks
const callback1 = (key: string, value: unknown) => {
if (typeof value !== 'number' || Number.isNaN(value)) throw new Error('error ' + key)
return value
}
const callback2 = (key: string, value: unknown, min: number, max: number = Infinity) => {
if (typeof value !== 'number' || Number.isNaN(value)) throw new Error('error ' + key)
if (value < min || value > max) throw new Error('error')
return value
}
const callback3 = (key: string, value: unknown, something: number) => {
if (typeof value !== 'number' || Number.isNaN(value)) throw new Error('error ' + key)
if (value === something) throw new Error('error')
return value
}
type Obj = { [P: string]: unknown }
const tesstobj: Record<string, unknown> = { one: 1, two: 'two' }
const evaluate_two = <
O extends Obj,
F1 extends () => ReturnType<F1>
>(obj: O, prop: keyof O, vfunc: F1) => {
if (typeof prop !== 'string') throw new Error('error')
return vfunc();
}
evaluate_two(tesstobj, 'one', () => {
callback1('one', tesstobj['one']);
})
evaluate_two(tesstobj, 'one', () => {
const temp_min = -10;
const temp_max = 10;
callback2('one', tesstobj['one'], temp_min, temp_max);
})
evaluate_two(tesstobj, 'one', () => {
const something = 100;
callback3('one', tesstobj['one'], something);
})
编辑(根据@bogdanoff的评论更新答案):
// callbacks
const callback1 = (key: string, value: unknown) => {
if (typeof value !== 'number' || Number.isNaN(value)) throw new Error('error ' + key)
return value
}
const callback2 = (key: string, value: unknown, min: number, max: number = Infinity) => {
if (typeof value !== 'number' || Number.isNaN(value)) throw new Error('error ' + key)
if (value < min || value > max) throw new Error('error')
return value
}
const callback3 = (key: string, value: unknown, something: number) => {
if (typeof value !== 'number' || Number.isNaN(value)) throw new Error('error ' + key)
if (value === something) throw new Error('error')
return value
}
type Obj = { [P: string]: unknown }
const tesstobj: Record<string, unknown> = { one: 1, two: 'two' }
const evaluate = <
O extends Obj,
F extends (key: string, val: unknown) => ReturnType<F> // <--
>(obj: O, prop: keyof O, vfunc: F) => {
if (typeof prop !== 'string') throw new Error('error')
return vfunc(prop, obj[prop])
}
const evaluate_two = <
O extends Obj,
F extends (key: string, val: unknown, ...args: any[]) => ReturnType<F> // <--
>(obj: O, prop: keyof O, vfunc: F , ...args: any[]) => {
if (typeof prop !== 'string') throw new Error('error')
return vfunc(prop, obj[prop], ...args)
}
evaluate_two(tesstobj, 'one', callback1)
evaluate_two(tesstobj, 'one', callback2)
evaluate_two(tesstobj, 'one', callback3)
只需将参数类型从known[]更改为any[]。希望这有帮助。