[英]Typescript generic related
export interface Dispatch<A extends Action = AnyAction> { <T extends A>(action: T): T }
這個聲明是一個調用簽名。 等效的聲明是:
export type Dispatch<A extends Action = AnyAction> =
<T extends A>(action: T) => T
這同樣可以在 TypeScript 文檔中看到: Generic Types 。
因此,這意味着:
任何類型為
Dispatch<A>
函數(其中 A 是自由類型變量,其具體類型應擴展Action
並默認為AnyAction
)接收類型(T
)擴展A
任何值並返回相同類型的值(可能是它本身) .
類型聲明中的類型參數(此處為A
)與函數類型聲明(此處為T
)之間的重要區別在於,前者允許您指定函數實現的特定子類型或調用者應期望的子類型,而后者意味着函數應該接受滿足約束的任何類型,調用者可以假設它可以接受任何這樣的類型。
讓我們檢查一下這個界面:
interface Dispatch<A extends Action = AnyAction> {
<T extends A>(action: T): T;
}
首先,接口Dispatch
在A
是通用A
,因此您可以指定A
以從中獲取具體類型。 指定的類型A
被限制為可分配給Action
東西,如果您不指定類型,它將默認為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
?
好吧,該接口具有單個調用簽名,因此可以將其用作函數。 讓我們看看簽名: <T extends FooAction>(action: T): T
。
這是一個泛型函數簽名,其類型參數T
必須可分配給FooAction
(或在Dispatch<A>
指定的任何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
。
所以,希望這是有道理的,它可以幫助你。 祝你好運!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.