Как сузить тип TypeScript generi c в интерфейсе на основе значения свойства этого интерфейса? - PullRequest
1 голос
/ 27 марта 2020

Как часто с проблемами TypeScript, трудно объяснить, что я хочу сделать со словами, но следующий код должен помочь понять это.
Итак, у меня многоуровневая структура данных (я сохранил только 2 уровня глубины) для примера, но он может иметь больше в реальности), и мне нужно сопоставить другую структуру данных с некоторыми из ее свойств.
Мой пример использования - написание объекта конфигурации, используемого для построения формы, для создания и редактирования этих данных. И для этого я хотел бы предоставить лучшее возможное автозаполнение.

Насколько я смог, я могу обеспечить автозаполнение для первого уровня, используя тип c в качестве записи, но не могу заставить его работать на более глубоких уровнях.
In В следующем коде вы увидите обходной путь, который делает автозаполнение работающим, но это бесполезно, поскольку он состоит из записи имени свойства (без автозаполнения), чего я и стараюсь избегать.

Это кажется сложным случаем но так как эксперты TypeScript способны достигать довольно сложных вещей, я надеялся, что у кого-то там может быть решение.
Я нашел этот ответ , который кажется связанным, но не смог построить решение для моего конкретного c варианта использования.

Вот детская площадка , демонстрирующая мою волю.

interface Foo {
    a
    b
    c: {
        c1
        c2
    }
    d: {
        d1
        d2
    }
}

interface Bar<T> {
    name: keyof T,
    child: Bar<any> // Here I would like to pass something like T[value of name] instead of any.
}

// Problematic case:
<Bar<Foo>>{
    name: 'c', // Autocomplete works here.
    child: {
        name: '' // Autocomplete doesn't work here (should propose 'c1' or 'c2').
    }
};

// Workaround:
<Bar<Foo>>{
    name: 'c',
    child: <Bar<Foo['c']>>{ // Here I would like the type to be deduced automatically instead of having to assert it.
        name: 'c1' // Autocomplete works here too.
    }
};
...