Примечание. Следующий ответ был протестирован на TS3.5 в режиме --strict
.Ваш пробег может отличаться, если вы используете другие версии или флаги компилятора.
Как насчет этого:
function flattenArrayByKey<K extends keyof any, V>(array: Record<K, V[]>[], prop: K): V[] {
return array.reduce((arr, item) => [...arr, ...(item[prop] || [])], [] as V[]);
}
Вы должны сообщить компилятору, что T[TProp]
будетмассив.Вместо того, чтобы пытаться пойти по этому пути, у меня есть общие обозначения: K
(который вы называли TProp
) и V
, тип элемента свойства массива в array[number][K]
.Затем вы можете ввести array
как Record<K, V[]>[]
вместо T[]
(A Record<K, V[]>
- это объект, свойство которого по ключу K
имеет тип V[]
).И это возвращает V[]
.
Теперь компилятор понимает, что вы пытаетесь сделать, хотя вам нужно сказать ему, что исходный пустой массив в качестве второго параметра для reduce
должен быть V[]
(следовательно, [] as V[]
).
И это должно работать так, как вы хотите.Надеюсь, это поможет;удачи!
Ссылка на код
Обновление: вышеупомянутое, кажется, не очень хорошо подходит, когда объект имеет массивы различных типов.Возможно, вам придется вводить его явно, например, flattenArrayByKey<"anotherArray", number>(objectsWithNestedProperties, "anotherArray")
, что является избыточным и раздражающим.
Ниже приведена более сложная подпись, но она имеет лучший вывод и лучшие предложения IntelliSense:
type ArrayKeys<T> = { [K in keyof T]: T[K] extends any[] ? K : never }[keyof T];
function flattenArrayByKey<T extends Record<K, any[]>, K extends ArrayKeys<T>>(
array: T[],
prop: K
): T[K][number][] {
return array.reduce(
(arr, item) => [...arr, ...(item[prop] || [])],
[] as T[K][number][]
);
}
Он должен вести себя одинаково с точки зрения входов и выходов, но если вы начнете набирать
const result = flattenArrayByKey(objectsWithNestedProperties, "");
// put cursor here and get intellisense prompts (ctrl-spc) ---^
Он предложит "arrayProperty"
(а теперь "anotherArray"
) в качестве второго параметра, поскольку только arrayProperty
(и "anotherArray"
) подходит для такого сокращения.
Надеюсь, это поможет снова.Удачи!
Ссылка на код