【问题标题】:How to infer parameter type in TypeScript?如何在 TypeScript 中推断参数类型?
【发布时间】:2021-04-28 11:27:32
【问题描述】:

如何推断参数类型?

我想实现一个类似redux的状态管理库,但在定义类型方面遇到了麻烦。 原型如下:


interface IModel<S, A> {
  state: S
  action: IActions<S, A>
}

type IActions<S, A> =  {
  [K in keyof A]: (state: S, payload: ???) => void // `???` How should it be defined here
}

class Model<T,A> implements IModel<T,A>{
  //...
}

// examples

const model=new Model({
  state:{name:"foo"},
  action:{
    setName:(state,name: string)=>{
      //...
    },
    fetchAccount:(state,payload: {
      id: number,
      locked: boolean,
      ...
})=>{
      //...
    }
  }
})

//
let state={name:''}
model.action.setName(state,'bar') // ok
model.action.setName(state,123)   // error

【问题讨论】:

  • TypeScript 不是 C#,因此请不要使用 I 作为接口的类型名称前缀。
  • 另外,你不使用the official TypeScript bindings for Redux有什么原因吗?你读过redux.js.org/recipes/usage-with-typescript 吗?
  • 这里的Model和IModel仅用于问题描述,更直观。实际代码中根本没有 IModel 接口的定义。它与 redux 相同,但其表示和实现方式不同。无论如何,谢谢你的回答。

标签: javascript reactjs typescript typescript-generics react-typescript


【解决方案1】:

如果您想在方法名称与状态属性名称匹配的特定情况下进行严格的类型检查,您可以使用template literal types and mapped type as clauses。这需要 Typescript 4.1 或更高版本。

一般要点是获取状态键(在本例中为 name),并将它们映射到具有正确签名 ((state: State, value: string) =&gt; void) 的相应方法名称 (setName)。

type Actions<State> = {
  [K in keyof State & string as `set${Capitalize<K>}`]: (state: State, value: State[K]) => void;
}

type Model<State> = {
  state: State;
  actions: Actions<State>;
}

const model: Model<{ name: string }> = {
  state: {
    name: 'foo',
  },
  actions: {
    setName(state, value) {
      state.name = value;
    }
  }
};

【讨论】:

  • 如果你看不出来,我很难通过这个问题得到nerd sniped
  • 你的方法很接近,但是action不是set开头的固定方法。方法名和参数不受限制,参数不一定与状态匹配。我将再次修改上面的例子,使其更清晰
  • @jun 您不能为任意操作设置类型安全性。在最简单的情况下,假设一个字段是字符串而另一个字段是数字的状态,无法推断您应该将哪个字段传递给任意命名的操作。
  • 这是目前的问题,所以我只是发帖求助
猜你喜欢
  • 2016-12-05
  • 2021-04-09
  • 2021-09-08
  • 1970-01-01
  • 2018-12-13
  • 2020-03-11
  • 2019-04-26
  • 2022-01-26
  • 1970-01-01
相关资源
最近更新 更多