В настоящее время я играю с typescript@next
, в котором теперь объединены PR условных типов.
Что я пытаюсь сделать, так это создать метод, который берет глубокую запись для типа модели данных и возвращает своего рода глубокий выбор на основе полей в записи. Например, я хочу иметь возможность сделать следующее:
loadUser({
id: true,
name: {
first: true
}
});
Когда тип User
выглядит как
type User = {
name: {
first: string;
last: string;
};
id: string;
}
и возвращаемое значение loadUser
в этом случае будет соответствовать
{
id: string;
name: {
first: string;
}
}
Что я сделал до сих пор, так это следующее:
type DeepSelect<T> = {[K in keyof T]?: T[K] extends string ? boolean : DeepSelect<T[K]>};
type DeepPick<T, S extends DeepSelect<T>> = {[K in keyof S]: S[K] extends DeepSelect<infer U> ? DeepPick<T[K], U> : T[K]}
function loadUser<S extends DeepSelect<User>>(select: S): DeepPick<User, S> {
...
}
Проблема двоякая:
- Любое использование
T[K]
в ошибках определенияDeepPick
сtype K cannot be used to index type T
.
Я чувствую, что, учитывая определение DeepSelect
, в котором все ключи происходят от ключей в его общем T
, T[K]
здесь вполне допустимо, потому что любые ключи в S
также будут ключами в T
.
<удар>2. Последнее использование S[K]
в ошибках определения DeepPick
говорит о том, что type boolean | DeepSelect<T[K]> is not assignable to type DeepSelect<T[K]>
И здесь я чувствую, что, поскольку эта часть условия типа выполняется только в том случае, если S[K]
не расширяет логическое значение, тогда он должен иметь возможность сделать вывод, что S[K]
не boolean | DeepSelect<T[K]>
, а вместо этого только DeepSelect<T[K]>
Я понимаю, что, поскольку этот PR был объединен только вчера, не многие люди будут иметь обширное представление об этих вопросах, но я был бы очень благодарен, если бы кто-нибудь помог мне понять, как я могу правильно структурировать эти типы.
Обновление 1
Хорошо, я думаю, что решил проблему № 2, используя, также новый, вывод типов. Я изменил определение типа DeepPick
с:
type DeepPick<T, S extends DeepSelect<T>> = {[K in keyof S]: S[K] extends boolean ? T[K] : DeepPick<T[K], S[K]>}
to:
type DeepPick<T, S extends DeepSelect<T>> = {[K in keyof S]: S[K] extends DeepSelect<infer U> ? DeepPick<T[K], U> : T[K]}