【发布时间】:2017-03-14 00:48:39
【问题描述】:
我有一个这样的函数接口:
interface Callback {
(a: string, b: number): void;
}
而且我可以在不声明参数类型的情况下实现它:
const callback: Callback = (a, b) => { }
在这种情况下,TypeScript 理解 callback 的参数类型实际上是 (a: string, b: number)。
但是,如果我用一个类型的参数声明它,例如b: number:
const callback: Callback = (a, b: number) => { }
另一个参数a的类型变成any。 Example in the Playground。奇怪的是编译器确实知道a 应该是什么类型,因为它不会让你错误地定义它,例如(a: boolean, b: number) 会说参数不兼容。为什么不推断a的参数类型?
上面是一个简单的例子,但在尝试生成类型安全的Redux reducer map时让我有些头疼:
interface IReducer<TState> {
(state: TState, action: IAction): TState;
}
interface IReducerMap<TState> {
[actionType: string]: IReducer<TState>;
}
interface MyState { hello: string; }
interface MyAction extends IAction { say: string; }
const myReducerMap: IReducerMap<MyState> = {
// Result: `(state: MyState, action: IAction) => MyState`
// But I get an error on `action.say` not defined in `IAction`
reducer1: (state, action) => {
return { hello: action.say };
},
// Result: `(state: any, action: MyAction) => computed`
reducer2: (state, action: MyAction) => {
return { hello: action.say + state.this_should_be_an_error };
},
// Works but relies on you to correctly defining state
reducer3: (state: MyState, action: MyAction) => {
return { hello: action.say };
}
}
由于每个函数都将IAction 的子类型作为其action 参数(在本例中为MyAction),因此我必须在回调参数中声明其类型。但是一旦我声明了它的类型,我就失去了state 的类型,我必须声明它。当我有几十个回调和一个像DataImportMappingState 这样的真实状态名称时,这很烦人。
【问题讨论】:
-
AFAIK,从值推断的类型可以扩大声明的类型,尽管它非常违反直觉(所以也许我缺少一些东西)。
标签: typescript