簡體   English   中英

根據字符串文字參數將回調參數類型鍵入函數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM