![](/img/trans.png)
[英]Which is the best way to define the type of dynamic data-attributes in a React component?
[英]What is the best way to define a type of dynamic callback?
我有(在 TypeScript 中)一个名为“Instructions”的 class,它有一个名为“operate”的 static 方法。 此方法接受两个确定的 arguments,以及另外两个可能的。 第一个参数是“操作”方法应该调用的“回调函数”,arguments 的 rest 与将传递给回调 function 的 arguments 相同,我作为第一个参数获得了回调函数。 我的问题是,如何定义回调function的类型。
起初,我想这样实现它:
interface Operand {
// ...
}
interface OperationFunc {
(dstOperand: Operand, srcOperand?: Operand, powerEvaluation?: number): void;
}
class Instructions {
static operate (callback: OperationFunc, dstOperand, srcOperand?, powerEvaluation?) {
callback(dstOperand, srcOperand, powerEvaluation);
}
}
由于几个原因,结果证明是不成功的。 主要原因是每次调用回调function不是同一个function。 但是 - 这些是不同的功能,每次我根据需要传递不同的回调 function。 有时它是一个 function 接收单个“操作数”类型参数,有时它是一个 function 接收两个“操作数”类型 arguments,有时它是一个 function 接收三个 arguments - 其中两个是“操作数”类型,第三个是“数字”类型。 这三种类型的函数返回 void。
interface Operand {
// ...
}
type Function1 = (dst: Operand) => void; // The first type of callback functions
type Function2 = (dst: Operand, src: Operand) => void; // The second type of callback functions
type Function3 = (dst: Operand, src: Operand, powerEvaluation: number) => void; // The third type of callback functions
有谁知道如何定义这种回调 function 的类型?
使用generics和实用程序类型,您可以定义一个类型,该类型一般应用于您提供的类型 arguments。例如,您可以定义一个 function,它将另一个 function 作为参数,以及该 function 的参数。
function wrapper<
T extends (...params: any[]) => any
>(func: T, ...params: Parameters<T>): ReturnType<T> {
return func(...params);
}
function theFunc(x: string, y: number, z: string) {
return x + " " + y + " " + z;
}
console.log(wrapper(theFunc, "i would like", 1, "tall glass of milk"));
在操场上看到它。
重载签名会给你正确的想法。
static operate (callback: (a: Operand) => void, dstOperand: Operand);
static operate (callback: (a: Operand, b: Operand) => void, dstOperand: Operand, srcOperand: Operand);
static operate (callback: (a: Operand, b: Operand, c: number) => void, dstOperand: Operand, srcOperand: Operand, powerEvaluation: number);
static operate (callback: (a: Operand, b: Operand, c: number) => void, dstOperand?: Operand, srcOperand?: Operand, powerEvaluation?: number) {
callback(dstOperand, srcOperand, powerEvaluation);
}
现在有一个function可以通过四种方式调用。 所以它将接受所有这些调用。
Instructions.operate((a) => {}, 0);
Instructions.operate((a, b) => {}, 0, 0);
Instructions.operate((a, b, c) => {}, 0, 0, 0);
但是它会拒绝这个
Instructions.operate((a, b) => {}, 0);
一句警告。 此签名还将接受以下(可能是错误的)调用。
Instructions.operate((a) => {}, 0, 0);
那是因为(a) => {}
的类型被推断为(a: Operand) => void
。 类型为(a: Operand) => void
的 function 完全允许使用两个 arguments,或三个 arguments,或任意多个 arguments。 Javascript(和 Typescript)总是允许 function 占用额外的 arguments 并默默地丢弃它们。 由于 Typescript 无法区分一个参数的 function 和忽略其第二个参数的两个 arguments 的 function 之间的区别,因此它认为(a) => {}
实际上是 function 中的两个 884225120046 我不知道有什么方法可以解决这个问题,因为类型检查器实际上是正确的,代码将运行(尽管它可能是程序员错误)。
我们可以使用重载来描述这个 function 的可能行为:
static methymethod(callback: Function1, ...args: Parameters<Function1>): void;
static methymethod(callback: Function2, ...args: Parameters<Function2>): void;
static methymethod(callback: Function3, ...args: Parameters<Function3>): void;
static methymethod(callback: Function1 | Function2 | Function3, ...args: Parameters<Function1 | Function2 | Function3>) {
前 3 个“声明”声明了每个 function 的每个重载,最后一个只是将它们全部组合在一起。
但是,当尝试调用回调时,我们收到一个错误:
The 'this' context of type 'Function1 | Function2 | Function3' is not assignable to method's 'this' of type '(this: null, dst: Operand) => void'.
Type 'Function2' is not assignable to type '(this: null, dst: Operand) => void'.(2684)
这是因为 TypeScript 不知道调用的 function 应该接收正确的 arguments,但我们知道如果强制执行重载签名是安全的。
对于运行时类型检查,您可以检查args
的长度,但可以通过使用@ts-ignore
忽略它或将callback
类型更改为更通用的类型(如Function
或什至any
.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.