[英]Type callback argument to function based on string literal argument
我正在嘗試鍵入某些函數,以便在使用該函數時獲得正確的類型,同時在使用時盡量減少顯式鍵入。 本質上,該函數如下所示,我的目標是根據作為fntype
參數傳遞的字符串鍵入回調函數的arg
。
fn(fntype: string, callback: (arg: any) => void): void;
例如,
fn('foo', (foo) => {
foo.somethingInTheFooInterface;
}
fn('bar', (bar) => {
bar.somethingInTheBarInterface;
}
這些是我想出的類型:
type FooType = "FooType";
const FooType: FooType = 'FooType';
type BarType = 'BarType';
const BarType: BarType = 'BarType';
type ActionTypes = FooType | BarType;
interface Action<T> {
type: T;
}
interface FooInterface extends Action<FooType> {
somethingOnTheFooInterface: string;
}
interface BarInterface extends Action<BarType> {
somethingOnTheBarInterface: string;
}
type CallbackTypes = FooInterface | BarInterface;
type Callback<T extends CallbackTypes> = (action: T) => void;
function fn<T extends CallbackTypes, U extends ActionTypes>(actionType: U, cb: Callback<T>): void;
function fn (actionType, cb) {
cb();
}
明確使用事物時,哪種方法工作正常:
// Works fine if we explicitly type the arg
fn(FooType, (arg: FooInterface) => {
arg.somethingOnTheFooInterface
});
// Works fine if we define the generics when calling
fn<FooInterface, FooType>(FooType, arg => {
arg.somethingOnTheFooInterface;
});
但不要基於第一個參數鍵入回調:
// TypeError as arg is typed as the union type CallbackTypes
fn(FooType, arg => {
arg.somethingOnTheFooInterface
})
如果有人可以提供有關如何實現此鍵入的任何指導,那么我將不勝感激。
如果我正確理解您的話,那似乎是一個重大的過大殺傷力。
您應該能夠通過簽名重載實現目標:
interface FooInterface {
somethingOnTheFooInterface: string;
}
interface BarInterface {
somethingOnTheBarInterface: string;
}
fn(fntype: "FooType", callback: (arg: FooInterface) => void): void;
fn(fntype: "BarType", callback: (arg: BarInterface) => void): void;
fn(type: string, callback: (arg: any) => void) { ... }
從Typescript 2.9開始,在沒有函數重載的情況下,可以使用條件類型:
type FooType = "FooType";
const FooType: FooType = "FooType";
type BarType = "BarType";
const BarType: BarType = "BarType";
type ActionTypes = FooType | BarType;
interface Action<T> {
type: T;
}
interface FooInterface extends Action<FooType> {
somethingOnTheFooInterface: string;
}
interface BarInterface extends Action<BarType> {
somethingOnTheBarInterface: string;
}
type CallbackTypes<T> =
T extends FooType ? FooInterface :
T extends BarType ? BarInterface :
never;
type Callback<T> = (action: T) => void;
function fn<T extends ActionTypes, U extends CallbackTypes<T>>(actionType: T, cb: Callback<U>) {
cb({} as any);
};
fn(FooType, arg => {
arg.somethingOnTheFooInterface
})
fn(BarType, arg => {
arg.somethingOnTheBarInterface
})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.