簡體   English   中英

在Typescript中,基於函數重載定義強制通用類型參數滿足類型約束

[英]In Typescript force generic type parameter to satisfy the type constraints based upon function overload definitions

下面給出了簡化問題的必要代碼框架。 基本上,可以有不同類型的Source對象。 為簡單起見,下面的代碼中顯示了兩種類型的源: DirectSourceIndirectSource 函數sourceAdapter()接受Source和其他幫助程序參數。

在示例中:如果缺少參數keySource必須是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;
  }
}

錯誤產生的行標有星號。 這是到游樂場的鏈接。

最簡單的清潔方法就是將ReturnType更改為並集。 請享用。 游樂場鏈接

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 object>(
  src: Source<T>,
  key?: keyof T | (keyof T)[]
): 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 as IndirectSource<T>;
    } 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;
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM