TypeScript 类型推断 - 函数的通用对象

Posted

技术标签:

【中文标题】TypeScript 类型推断 - 函数的通用对象【英文标题】:TypeScript Type Inference - Generic Object Of Functions 【发布时间】:2019-12-09 21:09:12 【问题描述】:

我试图实现一个通用函数,它接受函数和数据的接口,并相互传递结果。

推理被破坏,任何帮助将不胜感激。

Link to a CodeSandbox of the Code That Does Not Compile

function InitViewModel<S, C, M>(params: 
  state: S;
  computed: (s: S) => C;
  methods: (s: S, c: C) => M;
) 
  const state = params.state;
  const computed = params.computed(state);
  const methods = params.methods(state, computed);
  return 
    state,
    computed,
    methods
  ;


export const VM = InitViewModel(
  state:  message: "This Will Be Infered As expected" ,
  computed: (state /* infered */) => (
    computedMessage: state.message + " But This Will Not"
  ),
  methods: (state /* infered */, computed /*  inferred wrong */) => 
    return 
      logName: () => console.log(state.message),
      logComputedName: () => console.log(computed.computedMessage) // Does not compile
    ;
  
);

【问题讨论】:

computed.computedMessage 不存在,因为computed 是一个函数。返回值有computedMessage 所以computed(someStatus).computedMessage 应该更有意义。但我不明白你想做什么。 @DanieleAlessandra,已经按照你描述的方式调用了,我已经修改了代码使其更清晰。 @Daniel 在过去的 45 分钟里我一直在敲我的脑袋,不认为有办法做到这一点而不将其拆分为多个参数,我只是无法让编译器去做参数的上下文类型并得到正确推断的返回类型C。可能是这两个功能工作方式的限制。也许其他人有一些想法.. @TitianCernicova-Dragomir。感谢 45 分钟,在 Twitter 上关注你 :-) 我知道拆分参数解决方案。再次感谢。 【参考方案1】:

我相信这在当前的 Typescript 版本中是不可能的。

我一直在试验您的代码,似乎 Type Inference 具有一些内部优先级,这表明类型应尽可能从参数推断,而不是从返回值推断。。 p>

如果您从代码中删除 methods 参数,您将看到 computed 返回值 - C,将被正确推断为:

 computedMessage: string 

当包含methods 时,C 被推断为unknown,因为它作为methods 中的参数存在,所以打字稿会更愿意尝试基于methods 行为而不是正确的类型computed.

【讨论】:

以上是关于TypeScript 类型推断 - 函数的通用对象的主要内容,如果未能解决你的问题,请参考以下文章

在 TypeScript 中推断泛型函数类型

打字稿:在对象内推断通用对象的类型

LayaBox---TypeScript---类型推论

TypeScript——类型检查机制

传递给通用函数包装器(如 _.debounce)的函数的类型推断

TypeScript在静态实现中推断出更通用的类型