类型安全地从对象中提取给定的字段集

问题描述

我从API调用中获得了一个json响应(以后将成为对象),我可以使用queryparams将其动态限制为某些字段。

我已经输入了完整的回复

现在我要实现的是创建一个类型,该类型接受给定的字段并返回仅包含给定属性的对象类型。

我知道有些实用程序类型如Pick,但是它们不适用于嵌套对象。

示例:

interface ResponseInterface {
    a: {
        a: {
            a: number;
            b: string;
        };
        b: {
            a: string;
            b: boolean;
        };
    };
    b: {
        a: object | null;
        b: string;
    }[];
}


const filters = ['a.a.a','a.b.b','b.a']; //nested properties seperated by dots
const fakeFullResponse: ResponseInterface = { //calling the api without any filters
            a: {
                a: {
                    a: 123,b: 'aab',},b: {
                    a: 'aba',b: true,b: [
                {
                    a: null,b: 'array bb',{
                    a: {},],};


interface ExpectedType { //after applying those filters to the object
    a: {
        a: {
            a: number;
        };
        b: {
            b: boolean;
        };
    };
    b: {
        a: null | object
    }[];
}

const fakeFilteredResponse: ExpectedType = { //calling the api with those fields above would get me this
            a: {
                a: {
                    a: 123,b: {
                    b: true,};

是否有给定ExpectedType接口和ResponseInterface的动态创建filters接口的方法?如果需要,可以更改filters数组的格式,只要嵌套结构保持不变

解决方法

首先,ResponseInterface.b的定义与ExpectedType.b相比没有什么意义,因为前者是具有固定长度2的元组,而后者是任意长度的数组(更新:OP已解决此问题)。因此,让我假设您的意思是这样:

interface ResponseInterface {
    a: {
        a: {
            a: number;
            b: string;
        };
        b: {
            a: string;
            b: boolean;
        };
    };
    b: {
        a: null | object;
        b: string;
    }[];
}

接下来,如果过滤器是以字符串形式编写的,那么您将需要TypeScript来解析字符串文字类型,该功能仅在即将发布的4.1版中存在。即使具有这种功能,由于要逐个而不是按结构列出筛选器,因此重新排列类型结构要困难得多。

因此,我建议您改用一种类型的过滤器格式:

type filters = { 'a': { 'a': 'a','b': 'b' },'b': 'a' };

格式应该是不言自明的。然后,您可以使用以下实用程序:

type PickStructure<T,F> = F extends keyof T ? { [k in F]: T[k] } : {
    [k in keyof F]: k extends keyof T ? (
        T[k] extends (infer U)[] ? PickStructure<U,F[k]>[] : PickStructure<T[k],F[k]>
    ) : never;
};

type ExpectedType = PickStructure<ResponseInterface,filters>;

它有效。看到这个Playground Link

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...