简体   繁体   English

将动态 json object 转换为 generics 输入 typescript

[英]Convert a dynamic json object into generics type in typescript

I want the following json object to convert into the equivalent generic type in typescript.我希望将以下 json object 转换为 typescript 中的等效泛型。

This json object has dynamic keys for example applications and permissions can have dynamic keys.这个 json object 有动态密钥,例如applicationspermissions可以有动态密钥。 The immediate keys inside applications for example application_management , user_management can be dynamic and also inside permissions , create_application , delete_application , update_application and so on can be dynamic as well.应用程序中的直接键,例如application_managementuser_management可以是动态的,在permissionscreate_applicationdelete_applicationupdate_application等内部也可以是动态的。

I have tried to do it using interface but didn't able to do it.我曾尝试使用界面来做到这一点,但没能做到。 Could you please help me solve this?你能帮我解决这个问题吗?

{
            "id": 1,
            "isSuperAdmin": true,
            "firstName": "Oleksii",
            "lastName": "",
            "email": "alexp@point2web.com",
            "gender": null,
            "dob": null,
            "photo": null,
            "status": "ACTIVE",
            "roles": [
                {
                    "id": 1,
                    "slug": "Head of Department-(Account Management-Network-P2W North America)"
                },
                {
                    "id": 2,
                    "slug": "Team Lead-(Account Management-Network-P2W North America)"
                },
                {
                    "id": 3,
                    "slug": "Employee-(Account Management-Network-P2W North America)"
                }
            ],
            "applications": {
                "application_management": {
                    "id": 41,
                    "slug": "application_management",
                    "appName": "Application Management",
                    "status": "ACTIVE",
                    "appType": "CODED",
                    "appUrl": "application-management",
                    "appIcon": "http://api.chromosome-studio.com/uploads/applications/application.png",
                    "permissions": {
                        "delete_application": {
                            "id": 3,
                            "action": "Delete Application",
                            "slug": "delete_application",
                            "level": "all"
                        },
                        "update_application": {
                            "id": 2,
                            "action": "Update Application",
                            "slug": "update_application",
                            "level": "all"
                        },
                        "create_application": {
                            "id": 1,
                            "action": "Create Application",
                            "slug": "create_application",
                            "level": "all"
                        }
                    }
                },
                "user_management": {
                    "id": 42,
                    "slug": "user_management",
                    "appName": "Application Management",
                    "status": "ACTIVE",
                    "appType": "CODED",
                    "appUrl": "user-management",
                    "appIcon": "http://api.chromosome-studio.com/uploads/applications/users.png",
                    "permissions": {
                        "create_application": {
                            "id": 4,
                            "action": "Create Application",
                            "slug": "create_application",
                            "level": "all"
                        }
                    }
                }
            }

HO, another Romain was faster. HO,另一个 Romain 更快。 But i have a little different solution但我有一点不同的解决方案

type Role = { id: number; slug: string };
type ObjectStatus = 'ACTIVE' | 'INACTIVE'; // add other status
type AppType = 'CODED' | 'DYNAMIC';
type PermissionLevel = 'all' | 'admin' | 'guest'; // add other levels

type ApplicationsType = 'user' | 'application';
type CrudTypes = 'delete' | 'update' | 'create';
type PermissionKeys = `${CrudTypes}_application`;

type Permission<NAME extends ApplicationsType, CRUD extends CrudTypes = CrudTypes> = {
    id: number;
    action: `${Capitalize<CRUD>} ${Capitalize<NAME>}`;
    slug: `${CRUD}_${NAME}`;
    level: PermissionLevel;
};

type Application<NAME extends ApplicationsType> = {
    id: number;
    slug: `${NAME}_management`;
    appName: `${Capitalize<NAME>} Management`;
    status: ObjectStatus;
    appType: AppType;
    appUrl: `${NAME}-management`;
    permissions: { [key in PermissionKeys]?: Permission<NAME> };

    [key: string]: unknown;
};

type ApplicationList = { [key in ApplicationsType as `${key}_management`]?: Application<key> };

type User = {
    id: 1;
    isSuperAdmin: true;
    firstName: string;
    lastName: string;
    email: string;
    gender: string | null;
    dob: string | null;
    photo: string | null;
    status: ObjectStatus;
    roles: Array<Role>;
    applications: ApplicationList;
};

When appliying this type to your input, i get compilation errors on将此类型应用于您的输入时,出现编译错误

  • application.user_management.appName which is awaited to be 'User Management' application.user_management.appName 等待成为“用户管理”
  • application.user_management.permission.create_application.action which is awaited to be 'Create User' application.user_management.permission.create_application.action 等待“创建用户”
  • application.user_management.permission.create_application.slug which is awaited to be 'create_user' application.user_management.permission.create_application.slug 等待成为“create_user”

A little update to better type permission list because this leads to not perfect typing.对更好的类型权限列表进行了一些更新,因为这会导致不完美的类型。

type PermissionList<NAME extends ApplicationsType> = { [key in CrudTypes as `${key}_${NAME}`]?: Permission<NAME, key> };

then replace in Application:然后在应用程序中替换:

permissions: PermissionList<NAME>;

That fire one more error on这又引发了一个错误

  • application.user_management.permission.create_application which is now awaited to be 'create_user', and allow only 'Create' as crud action. application.user_management.permission.create_application 现在等待成为“create_user”,并且只允许“创建”作为 crud 操作。

playground 操场

here is a type for your object:这是您的 object 的类型:

    type TypeForJsonObject = {
        id: number;
        isSuperAdmin: boolean;
        firstName: string;
        lastName: string;
        email: string;
        gender: string | null;
        dob: string | null;
        photo: string | null;
        status: "ACTIVE";
        roles: {
            id: number;
            slug: string;
        }[];
        applications: Record<string, {
            id: number;
            slug: string;
            appName: string;
            status: "ACTIVE";
            appType: "CODED";
            appUrl: string;
            appIcon: string;
            permissions: Record<string, {
                id: number;
                action: string;
                slug: string;
                level: "all";
            }>;
        }>
    };

What you ask for is the Record<KeyType,ValueType> wich allow you to have "dynamic" properties of given Type (here string keys for complex typed values.您要求的是 Record<KeyType,ValueType> 允许您拥有给定类型的“动态”属性(此处为复杂类型值的字符串键。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM