Я экспериментирую с Typescript, чтобы написать полный типизированный код, который выполняет запросы к существующему API REST.Этот API позволяет произвольное вложение моделей в запрос.Для простоты, скажем, у нас есть только две модели User
и Address
и подделка getUser
.Вот что я получил:
interface User {
id: string;
name: string;
age: number;
address: Address;
}
interface Address {
country: string;
city: string;
}
type UserSelector = {
id: null;
name: null;
age: null;
address: Partial<AddressSelector>;
};
type AddressSelector = {
country: null;
city: null;
};
function getUser<K extends keyof UserSelector>(_fields: Pick<UserSelector, K>): Pick<User, K> {
// return a mock object, will get from DB in real code
return {
id: "1",
name: "Jean Seberg",
age: 30,
address: { country: "FR", city: "Paris" },
} as Pick<User, K>;
}
const user = getUser({
//unknownField: null, // SHOULD TYPE ERROR, IT DOES
id: null,
age: null,
address: { country: null },
});
console.log(user.id, user.age, user.address.country);
//console.log(user.name); // SHOULD TYPE ERROR, IT DOES
console.log(user.address.city); // SHOULD TYPE ERROR, IT DOES NOT
Как видите, это работает не так, как ожидалось, user.address.city
должно выдавать ошибку типа компиляции, потому что ключ city
отсутствует в селекторе адресов.Понятно, почему это не работает, но я не знаю, как писать универсальным образом, чтобы он поддерживал любой уровень вложенности (жесткое кодирование типов с отношениями не представляется возможным).
Возможно ли это вМашинопись (любая версия).Как?