Я играю с примером, который применяет ограничения на то, как свойства в объекте могут ссылаться друг на друга. Предполагаемый вариант использования - создание типа «схема», который содержит типы «таблицы», которые могут быть связаны.
Дурачиться Я делаю следующее:
type Db<P extends Db<P>> = {
[K: string]: Table<P>;
};
type Table<P extends Db<P>> = {
refs: keyof P;
};
Я хочу сделать вывод о конечном вводить и повторно использовать их интересными способами, поэтому я создаю две служебные функции:
const schema = <TDb extends Db<TDb>>(db: TDb) => ({});
const table = <T extends Table<TDb>, TDb extends Db<TDb>>(tbl: T): T => ({} as T);
Идея состоит в том, чтобы определить схему в качестве аргумента в функции schema
и использовать функцию table
определить дочерние таблицы. Я хочу, чтобы свойство ref
было ограничено ключами таблицы, которые мы уже определили в нашей схеме.
К моему удивлению (и заслуга машинописи) написание схемы в виде буквального произведения:
schema({
foo: {
refs: 'bar', // Validated correctly, and intellisense suggests 'foo' | 'bar'.
},
bar: {
refs: 'foo',
},
});
Но, когда я пытаюсь использовать функцию полезности таблицы, я теряю доброту intellisense:
schema({
foo: table({
refs: 'bar', // Validated correctly, but no intellisense completion suggestions.
}),
bar: {
refs: 'foo',
},
});
Если я изменю свойство refs bar
на что-то недопустимое, например baz
, тогда машинопись жалуется. Ясно, что он знает, что это должно быть foo
или bar
, поэтому я предполагаю, что он выводит тип схемы из типа возврата требуемой table
функции.
Мне интересно, почему, тогда, это не предлагает их?
У меня есть настроенная игровая площадка здесь для тех, кто хочет попробовать это: