在Typescript中强制泛型类型参数,以满足基于函数重载定义的类型约束

问题描述 投票:0回答:1

下面给出了简化问题所需的代码框架。基本上,可以有不同类型的Source对象。为简单起见,下面的代码中显示了两种类型的源:DirectSourceIndirectSource。函数sourceAdapter()接受Source和其他辅助参数。

在示例中:如果参数key缺失,则Source必须是DirectSource;如果key是单个字符串值,那么Source必须是IndirectSource,并且在这两种情况下代码执行必要的调整并返回DirectSource对象。如果key是一个数组,那么Source应该是IndirectSource,它也是函数的返回值。


type KeyMap<T> = { [key in keyof T]: number };

type DirectSource = {
  value: number;
  otherFieldsAndMethods: any;
};

type IndirectSource<T extends object> = {
  kvMap: KeyMap<T>;
  otherFieldsAndMethods: any;
};

type Source<T extends number | object> = T extends object ? IndirectSource<T> : DirectSource;

// overloads
function sourceAdapter(src: Source<number>): DirectSource;
function sourceAdapter<T extends object>(src: Source<T>, key: keyof T): DirectSource;
function sourceAdapter<T extends object>(src: Source<T>, key: (keyof T)[]): IndirectSource<T>;

function sourceAdapter<T extends number | object>(
  src: Source<T>,
  key?: keyof T | (keyof T)[]
): T extends object ? IndirectSource<T> : DirectSource {

  if (key) { // According to function overloads Source must be an IndirectSource
    if (key instanceof Array) { // Config and return IndirectSource
      const kvMap = key.reduce((ac, s) => {
        ac[s] = (src as any).kvMap[s];
        return ac;
      }, {} as any);

      // ******Error here:
      // Type 'T' does not satisfy the constraint 'object'.
      let ret: IndirectSource<T> = {
        kvMap,
        otherFieldsAndMethods: src.otherFieldsAndMethods
      };
      return ret;
    } else { // Config and return DirectSource
      let directSource = {
        otherFieldsAndMethods: src.otherFieldsAndMethods,
        value: (src as IndirectSource<any>).kvMap[key],
      };
      return directSource; // ******Error here: assignability
    }
  } else { // Source is a DirectSource, simply return the src.
    return src;
  }
}

错误结果的行标有星号。 This is the link to the playground.

javascript typescript visual-studio-code typescript-generics
1个回答
1
投票

最简单最简单的方法就是将Return Type更改为union。请享用。 qazxsw poi

Playground link
© www.soinside.com 2019 - 2024. All rights reserved.