我有一个这样的功能界面:
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
),因此我必须在callback参数中声明其类型。但是一旦我声明它的类型,我就失去了state
的类型,我必须声明它。当我每次回调都有几十个回调和一个真实的州名如DataImportMappingState
时,这非常烦人。
答案 0 :(得分:4)
a
和b
的推断来自上下文输入。以前,如果所有参数未注释,参数仅在上下文中键入。
This behavior has changed in the latest build of the TypeScript compiler因为它似乎不直观。现在,上下文输入将应用于所有不具有显式类型注释的参数。