#Enforce repository return type is instance of class

2 messages · Page 1 of 1 (latest)

stone barn
#

TS is a tad annoying as it seems as though if your data shape matches a class, it's hard to enforce instance return types. This can be problematic if I want to leverage class-transformer.

So I have 2 options. Either find some way to enforce it, or have a global interceptor that automatically converts to class and converts back to plain for serialization purposes.

This is what I've come up with to enforce class return types. Is this an acceptable pattern? Would a global interceptor be the more appropriate choice here?

const brand = Symbol('user')

export class User {
  __brand = brand

  uuid: string
  username: string
  name: string
  type: 'admin' | 'user'
  created: string
  updated: string
  hashed_password: string

  constructor(user: Omit<User, '__brand'>) {
    Object.assign(this, user)
  }
}

function badReturnUser(): User {
  return { // error as it doesn't include the brand
    uuid: '',
    hashed_password: '',
    updated: '',
    created: '',
    type: 'admin',
    username: '',
    name: ''
  }
}

function goodReturnUser(): User {
  return new User({
    uuid: '',
    hashed_password: '',
    updated: '',
    created: '',
    type: 'admin',
    username: '',
    name: ''
  })
}
#

Also I'm potentially a bit concerned with class-transformer performance if I apply it across all of my routes. How well does it scale for say, a request that returns 300 entities which each have about 250 properties? Should I just shy away from class-transformer and look into something like AJV, zod, or typia?