答案 0 :(得分:1)
export interface Dispatch<A extends Action = AnyAction> { <T extends A>(action: T): T }
此声明为call signature。等效的声明为:
export type Dispatch<A extends Action = AnyAction> =
<T extends A>(action: T) => T
这又可以在TypeScript文档中看到:Generic Types。
因此,这意味着:
任何类型为
Dispatch<A>
的函数(其中A为自由类型变量,其具体类型应扩展为Action
,默认值为AnyAction
)将接收该类型的任何值({{1} })扩展T
并返回相同类型的值(可能是其自身)。
类型声明(此处为A
)中的类型参数与函数类型声明(此处为A
(此处)之间的重要区别在于,前者可让您指定函数实现的特定子类型或调用者应该期望它是,而后者意味着该函数应该接受任何满足约束的类型,并且调用者可以假定它可以接受任何这种类型。
答案 1 :(得分:1)
让我们检查一下这个界面:
interface Dispatch<A extends Action = AnyAction> {
<T extends A>(action: T): T;
}
首先,接口Dispatch
在A
中是通用的,因此您可以指定A
从中获取具体类型。指定的类型A
是constrained,可以分配给Action
,如果不指定类型,它将default到AnyAction
:>
let actionDispatcher: Dispatch<Action>; //okay
let anyActionDispatcher: Dispatch; // Dispatch<AnyAction>
let badDispatcher: Dispatch<string>; // error!
// not an Action ---------> ~~~~~~
interface FooAction extends Action {
foo: string;
}
let fooDispatcher: Dispatch<FooAction>; // okay
因此,一旦指定了A
,就可以通过将A
的所有实例替换为指定的类型来获得具体的类型。让我们看一下Dispatch<FooAction>
。你得到这个:
// same type as Dispatch<FooAction>
interface DispatchFooAction {
<T extends FooAction>(action: T): T;
}
所以,现在的问题是:什么是DispatchFooAction
?
好,该接口只有一个call signature,因此可以用作函数。我们来看一下签名:<T extends FooAction>(action: T): T
。
这是一个generic function签名,其类型参数T
必须可分配给FooAction
(或A
中指定的任何Dispatch<A>
);它采用T
类型的参数,并返回相同类型的值。
让我们看看是否可以实现并使用Dispatch<FooAction>
:
// good implementation
fooDispatcher = <T extends FooAction>(a: T) => a; // okay
const x = fooDispatcher({ type: "foo", foo: "" }); // okay,
// T inferred as { type: string; foo: string; }, x is of that type
const y = fooDispatcher({ type: "foo", foo: "", baz: 1 }); // okay,
// T inferred as { type: string; foo: string; baz: number; }, y is of that type
const z = fooDispatcher({ type: "foo" }); // error!
// missing foo prop --> ~~~~~~~~~~~~~~~
interface BarAction extends FooAction {
bar: string;
}
// bad implementation
fooDispatcher = <T extends BarAction>(a: T) => a; // error!
//~~~~~~~~~~~ <-- bar missing in FooAction but required in BarAction
良好的实现有效; fooDispatcher
是有效的Dispatch<FooAction>
,因为它是一个接受FooAction
或其任何子类型的输入并返回相同类型的函数。您可以看到x
和y
正确调用了该函数,但是z
没有正确调用该函数,因为输入不是有效的FooAction
。
错误的执行不起作用; <T extends BarAction>(a: T)=>a
仅声明接受BarAction
输入,但是fooDispatcher
必须接受任何 FooAction
,并非每个FooAction
都是BarAction
。
因此,希望这对您有所帮助。祝你好运!