2017-07-06 25 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) { ... }