TypeScript类型推断 - 泛型函数对象

3
我正在尝试实现一个通用函数,它接受函数和数据的接口,并将结果从一个传递到另一个。
推断已经出错,任何帮助将不胜感激。 链接到无法编译的CodeSandbox代码
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
@DanieleAlessandra,它已经按照您描述的方式被称呼了,我修改了代码以使其更清晰。 - Daniel
1
@Daniel 我已经苦思冥想了45分钟,似乎没有办法在不将其拆分为多个参数的情况下完成此操作。我无法让编译器对参数进行上下文类型推断并正确推断返回类型C。这可能是这两个功能工作方式的限制。也许其他人有一些想法... - Titian Cernicova-Dragomir
1
@TitianCernicova-Dragomir。感谢您的45分钟,我已经在Twitter上关注了您 :-) 我知道有关分割参数解决方案的信息。再次感谢。 - Daniel
1个回答

4
我认为在当前的TypeScript版本中不可能实现这个功能。
我已经尝试了你的代码,似乎类型推断会根据一定的优先级来判断类型是应该从参数中还是从返回值中进行推断。
如果你将代码中的methods参数删除,你会发现computed返回值-C会被正确地推断为:
{ computedMessage: string }

当包含 methods 时,C 被推断为 unknown,因为它作为一个参数存在于 methods 中,所以 TypeScript 更倾向于尝试基于 methods 的行为来获取正确的类型,而不是 computed


嗨@yuval.bl,你能给一个链接,指向TypeScript中哪一行代码应该“尽可能从参数推断优先级,而不是从返回值推断”吗? - Loi Nguyen Huynh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接