简体   繁体   English

如何在打字稿中为对象的通用键类型分配值类型?

[英]How assign a value type to a generic key type of an object in typescript?

I'm trying to write a function that merges, and sorts already sorted arrays into one sorted array.我正在尝试编写一个合并的函数,并将已经排序的数组排序为一个排序数组。 It accepts array of array of objects, and a key to compare which will be the base of the comparison.它接受对象数组的数组,以及将作为比较基础的比较键。 I need to make sure that the value of the provided key is always a number.我需要确保提供的键的值始终是一个数字。

Here's what I'm at so far:这是我到目前为止的情况:

const sortMerge = <
  A extends Array<I>,
  K extends keyof A[number],
  I = A[number] & {
    [key in K]: number;
  },
>(
  arrays: A[],
  key: K,
  sortMethod = SortMethod.asc,
) => {
  const indexesOfArrays = arrays.map(() => 0);

  const mergedSorted = [];

  while (arrays.some((array, i) => array.length > indexesOfArrays[i])) {
    const currentItemsOfArrays = arrays.map(
      (array, arrayIndex) => array[indexesOfArrays[arrayIndex]],
    );
    const comparison = currentItemsOfArrays.map((item) =>
      item ? item[key] : (sortMethod === SortMethod.asc ? Infinity : -Infinity),
    );

    const nextArrayIndex = comparison.indexOf(
      Math[sortMethod === SortMethod.asc ? 'min' : 'max'](...comparison),
    );
    const nextItem = currentItemsOfArrays[nextArrayIndex];

    mergedSorted.push(nextItem);
    indexesOfArrays[nextArrayIndex]++;
  }
  return mergedSorted;
};

Everything's fine, but it doesn't recognise I[K] as number , but that's what I was trying to do with defining both K , and I as generics.一切都很好,但它不会将I[K]识别为number ,但这就是我试图将KI定义为泛型。

What am I doing wrong?我究竟做错了什么?

Expected errors/types:预期的错误/类型:

 const missingKey = [ { a: 1 } ]; const valid = [ { a: 2, b: 3 } ]; const anotherValid = [ { c: 3, b: 4 } ]; sortMerge([missingKey, valid], 'b') // missingKey[number] is missing property 'b'; sortMerge([valid, anotherValid], 'b') // expected return type: ({ a: number, b: number } | { c: number, b: number })[]

I have changed generic constraints a bit:我稍微改变了通用约束:

enum SortMethod {
  asc = 'asc',
}
const sortMerge = <
  Key extends PropertyKey,
  Elem1 extends Record<Key, number>,
  Elem2 extends Record<Key, number>,

  Arr1 extends Elem1[],
  Arr2 extends Elem2[],
  Arrays extends [Arr1, Arr2]
>(
  arrays: [...Arrays],
  key: Key,
  sortMethod = SortMethod.asc,
): (Arrays[number][number])[] => {
  const indexesOfArrays = arrays.map(() => 0);

  const mergedSorted = [];

  while (arrays.some((array, i) => array.length > indexesOfArrays[i])) {
    const currentItemsOfArrays = arrays.map(
      (array, arrayIndex) => array[indexesOfArrays[arrayIndex]],
    );
    const comparison = currentItemsOfArrays.map((item) =>
      item ? item[key] : (sortMethod === SortMethod.asc ? Infinity : -Infinity),
    );

    const nextArrayIndex = comparison.indexOf(
      Math[sortMethod === SortMethod.asc ? 'min' : 'max'](...comparison),
    );
    const nextItem = currentItemsOfArrays[nextArrayIndex];

    mergedSorted.push(nextItem);
    indexesOfArrays[nextArrayIndex]++;
  }
  return mergedSorted;
}

const missingKey = [{ a: 1 }];
const valid = [{ a: 2, b: 3 }];
const anotherValid = [{ c: 3, b: 4 }];

sortMerge([missingKey, valid], 'b') // missingKey[number] is missing property 'b';
const x = sortMerge([valid, anotherValid], 'b')

Playground 操场

If you want to infer keys of nested object or object in the array, you should start from the bottom.如果要推断数组中嵌套对象或对象的键,则应从底部开始。

Key - infered property of object Key - 对象的推断属性

Elem - infered object where keys are Key Elem - 推断的对象,其中键是Key

Arr - infered array of Elem Arr - 推断的Elem数组

Arrays - infered array of Arr Arrays - 推断的Arr数组

As you might have noticed, I have started from infering the bottom level of prop and finished infering the top argument.正如您可能已经注意到的那样,我从推断 prop 的底层开始,并完成了对顶层参数的推断。

If you are interested in type inference on function arguments, you can check my article如果您对函数参数的类型推断感兴趣,可以查看我的文章

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM