【问题标题】:TypeScript function implementation downgrades parameter types to `any` if you declare a param type如果您声明参数类型,TypeScript 函数实现会将参数类型降级为“任意”
【发布时间】: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的类型变成anyExample 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


【解决方案1】:

ab 的推断来自上下文输入。以前,只有在 所有 参数都未注释时,才会根据上下文键入参数。

This behavior has changed in the latest build of the TypeScript compiler 因为它似乎不直观。现在上下文类型将应用于所有没有显式类型注释的参数。

【讨论】:

  • 我发誓你是机器人。再次感谢瑞恩,我会在 9 分钟内接受 SO 允许的情况。 :)
猜你喜欢
  • 1970-01-01
  • 2019-02-26
  • 2023-02-09
  • 2012-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-30
相关资源
最近更新 更多