带有嵌套模式的类型化REST API

问题描述 投票:0回答:1

我正在尝试使用Typescript编写完整的类型代码,该代码向现有REST API发出请求。此API允许在请求中任意嵌套模型。为简单起见,假设我们只有两个模型UserAddress以及一个假的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不在地址选择器中。很明显为什么它不起作用,但我不知道如何以通用方式编写它以支持任何嵌套级别(具有关系的硬编码类型似乎不是一种选择)。

这可能在Typescript(任何版本)中。怎么样?

typescript typescript-generics
1个回答
0
投票

类型检查是正确的。

type UserSelector = {
    id: null;
    name: null;
    age: null;
    address: Partial<AddressSelector>;
};

type AddressSelector = {
    country: null;
    city: null;
};

address的属性UserSelectorPartial,这意味着AddressSelector的所有属性是可选的,所以如果没有显示city就可以了。

根据您的需要,您应该删除Partial并具体使用AddressSelector ['country']和AddressSelector ['city']的类型。

© www.soinside.com 2019 - 2024. All rights reserved.