改善
Kaizen  · Today I Learned by Ville Säävuori

Converting Django Enumeration Types to TypeScript Enums

I added a UserEvent model to one of my personal projects as an excercise in learning about working with event-like data. One of the attributes is event_type which uses a Django models.IntegerChoices (could be models.TextChoices as well) class that looks like this:

# models.py

class UserEventType(models.IntegerChoices):
    ACCOUNT_CREATED = 100, "Account created"
    ACCOUNT_DELETED = 101, "Account deleted"
    PROFILE_UPDATED = 102, "Profile updated"
    PASSWORD_RESET_ASKED = 103, "Password reset asked"
    PASSWORD_RESET_DONE = 104, "Password reset done"
    PASSWORD_CHANGED = 105, "Password changed"
    LOGIN = 200, "Login"
    LOGOUT = 201, "Logout"
    MAIL_SUBSCRIBE = 401, "Mail subscribed"
    MAIL_UNSUBSCRIBE = 402, "Mail unsubscribed"

I very quickly grew tired of trying to maintain the respective frontend TypeScript enums by hand so I wrote a quick & dirty management command that lets me copy paste full working code instead:

# core/management/commands/typescript_enums.py

from django.core.management.base import BaseCommand
from core.models import UserEventType


class Command(BaseCommand):
    help = "Outputs TypeScript enums for use in the frontend."

    def handle(self, *args, **options):
        print("*** TypeScript STARTS ***")
        print(" ")
        print("export enum UserEventType {")
        for name in UserEventType.names:
            print(f"  {name} = {UserEventType[name].value},")
        print("}")
        print(" ")
        print("*** TypeScript ENDS ***")

Running this command gives me this TypeScript:

export enum UserEventType {
  ACCOUNT_CREATED = 100,
  ACCOUNT_DELETED = 101,
  PROFILE_UPDATED = 102,
  PASSWORD_RESET_ASKED = 103,
  PASSWORD_RESET_DONE = 104,
  PASSWORD_CHANGED = 105,
  LOGIN = 200,
  LOGOUT = 201,
  MAIL_SUBSCRIBE = 401,
  MAIL_UNSUBSCRIBE = 402,
}

This gets me half of the equation but it’s super easy to extendd it to include the corresponding labels (if I’d want to build a form with dropdown etc) as well. The Django Enumeration types documentation together with reading the actual implementation (I wish Django docs had more links to the implementations!) was helpful in figuring this out.