Мой вариант использования следующий: у меня есть таблица, в которой столбцы и их значения определяются объектом headers
, например:
Для каждого filterable
столбца я хочу сгенерировать список элементов из другого объекта (data
) для подачи выборки.
Для простейшего случая, например столбца name
, метод получения элементов может быть таким же простым, как следующий:
Эти типы помогают мне гарантировать, что метод получения всегда будет возвращать string | number
для каждого фильтруемого
столбца.
Проблемы начинают возникать, когда у меня есть более сложные ключи, такие как formulatorUser.code
или особенно zdhc[0].subcategory
, где геттер должен быть чем-то вроде этого:
На этом этапе мне по сути нужно создать типизации для lodash.get с дополнительным ограничением, чтобы быть фильтруемым
столбцом. Я хотел позаимствовать Autopath
/Path
из ts-toolbelt
, но они выглядят сломанными (и еще более сломанными в последних версиях Typescript, вплоть до того, что их невозможно использовать).
Не могли бы вы предложить рабочую реализацию Path
/Autopath
, которая работает с массивами и вложенными объектами и помогает реализовать дополнительное ограничение filterable
?
const headers = [
{
key: 'data-table-select',
unhidable: true
},
{
title: t('name'),
align: 'start',
sortable: true,
filterable: true,
key: 'name'
},
{
title: t('formulator-code'),
align: 'start',
sortable: true,
filterable: true,
key: 'formulatorUser.code',
apiKey: 'code'
},
{
title: t('zdhc_subcategory'),
align: 'start',
sortable: true,
filterable: true,
key: 'zdhc[0].subcategory',
apiKey: 'subcategory'
},
] as const satisfies DataTableHeader[]
interface MyData {
id: string
name: string
formulatorUser: {
id: string
name: string
}
zdhc: Array<{
id: string
subcategory: string
}>
}
const data: MyData[] = [...]
(header) => [...new Set(data.map(el => el[header.key as ApiKey<typeof headers>]))]
type ApiKey<T extends Array<{ key: string; filterable?: boolean }>> = {
[K in keyof T]: T[K] extends { filterable: true }
? T[K] extends { key: string }
? T[K]['key']
: never
: never
}[number]
import { get } from 'lodash-es'
(header) => [...new Set(data.map(el => get(el, header.key)))]