2017-07-06 26 views
0

我想輸入一些函數來獲取正確的類型,當使用該函數時,在此使用點處顯式鍵入的最小值。本質上,該函數如下所示,並且我的目標是根據作爲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; 
}); 

但不會根據t鍵入回調他第一個論點:

// TypeError as arg is typed as the union type CallbackTypes 
fn(FooType, arg => { 
    arg.somethingOnTheFooInterface 
}) 

如果任何人可以提供任何指導如何實現這種打字,那麼我將不勝感激。

回答

1

如果我正確理解你,那麼它似乎是一個主要的矯枉過正。
您應該可以通過簽名重載實現您的目標:

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) { ... }