【问题标题】:Typescript: Generic Function to extract only defined values from a specific key from an Array of Objects打字稿:通用函数,仅从对象数组中的特定键中提取定义的值
【发布时间】:2021-11-25 20:05:30
【问题描述】:

我有两个功能完全相同的功能,因此它似乎是替代它们的通用功能的主要候选者。但是我不能完全正确,提取的值与原始类型不完全相同,因为返回类型应该是原始结果/错误类型,但现在没有未定义。

type Value = string;

type PurchaseResult = {
  result: Value | undefined,
  error: Error | undefined, 
}

该函数的现有示例之一(对于另一个函数,将键和类型替换为结果/值:

const extractErrors = (
  purchaseResults: PurchaseResult[]
) =>
  purchaseResults
    .map(({ error }) => error)
    .filter((error): error is Error => Boolean(error));

尝试失败


        const extractOnlyDefinedValuesFromArrayOfObjects = <
          T,
          K extends keyof A,
          A extends { [k in K]: T }
        >(
          list: A[],
          key: K
        ): T[] =>
          list
            .map((obj) => obj[key])
            .filter((value) => typeof value !== 'undefined');

        const extractedResults = extractOnlyDefinedValuesFromArrayOfObjects<
          Value,
          'result',
          PurchaseResult
        >('result', arrayOfResults);

谢谢!

【问题讨论】:

    标签: typescript typescript-generics


    【解决方案1】:

    这种语法Value || undefined 是不允许的,请改用|。 我不知道你是否定义了类型Value,这就是为什么我添加了T generic - for Value;

    考虑这个例子:

    type PurchaseResult<Value> = {
      result: Value | undefined,
      error: Error | undefined,
    }
    
    const extractErrors = <
      T,
      Key extends keyof PurchaseResult<T>,
      Data extends PurchaseResult<T>[]
    >(
      purchaseResults: Data,
      key: Key,
    ) =>
      purchaseResults
        .map(elem => elem[key])
        .filter((elem): elem is NonNullable<Data[number][Key]> => Boolean(elem));
    
    declare let results: PurchaseResult<number>[]
    
    const result = extractErrors(results, 'result') // number[]
    const result2 = extractErrors(results, 'error') // Error[]
    

    Playground

    我使用Data 只是别名PurchaseResult&lt;T&gt;[]。由于我们的列表有适当的泛型,我们可以使用NonNullable&lt;Data[number][Key]&gt; 作为我们的类型保护

    【讨论】:

      【解决方案2】:

      一个通用版本,它接受任何键值对数组并返回从每条记录中提取的指定键的类型化值数组。 (Playground)

      /**
       * extractKey extracts record[key] from an array of records 
       * @param key - a key in records
       * @param records - an array of key-value records of the same type
       * @return - `key` for each record, where record[key] is defined.
      */
      const extractKey = <T extends Record<string, any>, K extends keyof T>(
        key: K,
        records: T[]
      ): Array<NonNullable<T[K]>> => {
          return records
              .map(el => el[key])
              .filter(el => typeof el !== "undefined")
      }
      
      // define a type to test on, but can be any key-value pair type
      type PurchaseResult = {
        result?: number
        error?: string
      }
      
      // some dummy data
      const testMe: PurchaseResult[] = [{result: 1}, {error: "no result!"}, {result: 4}]
      
      
      // test it!
      const results = extractKey('result', testMe) // []number
      
      const errors = extractKey('error', testMe) // []string
      

      【讨论】:

        猜你喜欢
        • 2020-05-18
        • 2021-11-02
        • 2020-10-05
        • 2018-11-25
        • 1970-01-01
        • 2020-11-05
        • 1970-01-01
        • 2017-12-18
        • 1970-01-01
        相关资源
        最近更新 更多