我有一个这样的功能界面:
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
的参数类型?
以上是一个简单的例子,但在尝试生成类型安全_1029657时,它给了我一些头痛:
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
时,每次回调都很烦人 .
1 回答
a
和b
的推断来自上下文类型 . 以前,如果所有参数都未注释,则参数仅在上下文中键入 .This behavior has changed in the latest build of the TypeScript compiler因为它似乎不直观 . 现在,上下文类型将应用于没有显式类型注释的所有参数 .