Как стать автором
Обновить

Комментарии 5

В общем случае для таких штук удобнее не юнион вообще всех ключей сразу собирать, а постепенно выдавать подсказки по уровням вложенности (как в иде). Это решает проблемы со слишком большими юнионами, вычисляемыми ключами и массивами.

Чтобы примерно так работало:

const data = { foo: { a: string, b: number }, bar: string }

validatePath(data, "")
//                  ^ 'foo' | 'bar'

validatePath(data, "foo.")
//                      ^ 'foo.a' | 'foo.b'

Чорт возьми, это можно сделать! У меня получилась очень странная конструкция (можно ли проще?), которая работает в TS 5.2+

Набросок (без фильтров по массивам и т.д., просто сама идея)
type GetKeys<
    O extends object,
    K extends string,
    P extends string = '',
> = K extends `${infer I}.${infer X}`
    ? I extends keyof O
        ? O[I] extends object
            ? GetKeys<O[I], X, `${P}${I}.`>
            : never
        : never
    : `${P}${string & keyof O}`;

declare const validatePath: <
    O extends object,
    P extends string,
    P2 extends GetKeys<O, P>
>(ob: O, p: (P | P2) & GetKeys<O, P2>) => P;


// ---- пример использования -------

const obj = {
    aaa: {
        aa: {
            qq: 1,
            qq1: {
                preved: 2,
            },
            ww: 3,
        },
        bb: {
            zz: 4,
            xx: {
                tt: 5,
            },
        },
    },
    abb: {
        m: 6
    }
};

const r = validatePath(obj, ''); // печатать здесь

Воистину нет более черной магии, чем вывод типов в тайпскрипте..

Можно например так сделать (не знаю насколько проще, но имхо понятнее):

declare const validatePath: <
    O extends object,
    P extends string,
>(ob: O, p: P extends GetKeys<O, P> ? P : GetKeys<O, P>) => P;

Да, это лучше. И примерно понятно, как работает - в P просто подставляется текущее переданное значение. Кстати, тоже TS 5.2+, видно что-то там поменяли в выводе типов.

Звучит интересно, но итоговый код использую несколько месяцев и пока что не возникало такой необходимости. Думаю, когда столкнулись, переделаю под новые требования.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации