Home > database >  Convert a dynamic json object into generics type in typescript
Convert a dynamic json object into generics type in typescript

Time:01-12

I want the following json object to convert into the equivalent generic type in typescript.

This json object has dynamic keys for example applications and permissions can have dynamic keys. 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.

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": "[email protected]",
            "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"
                        }
                    }
                }
            }

CodePudding user response:

HO, another Romain was faster. 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.permission.create_application.action which is awaited to be 'Create User'
  • application.user_management.permission.create_application.slug which is awaited to be '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.

playground

CodePudding user response:

here is a type for your 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.

  • Related