How easily get your DTO in TypeScript

I changed my mind after years of mentally not supporting TypeScript ๐Ÿ˜ˆ

When I first interacted with this wrapper 10-12 years ago, I felt that true JavaScript believers should use JavaScript and not pretend that JavaScript is not prototype-based. Instead, they play with interfaces ๐Ÿคข and classical inheritance ๐Ÿคข like they do not know what happens under the hood.
I felt "M๐Ÿ’ฒ" had tried to convert JavaScript into C#, and it just happened that I tried to convert myself from the .NET stack to the NodeJS stack.

But it's another story. Today, I can say Microsoft did it pretty well. Thanks.

Thus, I want to share with my type I use across projects (I change it depending on needs).

It helps me to convert a complex domain type into a payload type, a DTO I use in a communication layer for receiving commands or requests.

type ConvertToDto<Props> =
  Props extends Array<infer T>
    ? Array<ConvertToDto<T>>
    : {
        [Property in keyof Props]: Props[Property] extends Date
          ? string
          : Props[Property] extends boolean
            ? boolean
            : Props[Property] extends string
              ? string
              : Props[Property] extends number
                ? number
                : Props[Property] extends Array<infer R>
                  ? ConvertToDto<Array<R>>
                  : ConvertToDto<Props[Property]>
      }

And the usage:

type TestBloodScheduleTime = {
  hour: Hour
  minutes: Minutes
  tz: TimeZoneOffset
}
type TestBloodScheduleTimeDto = ConvertToDto<TestBloodScheduleTime>

// The result is this ๐Ÿ‘‡๐Ÿ‘‡๐Ÿ‘‡
type TestBloodScheduleTimeDtoResult = {
  hour: number
  minutes: number
  tz: number
}
Artur Wojnar

Stuck on a hard technical decision?

Book a short call and let's talk about where you're stuck.

Book a call >>
๐Ÿ‡ฌ๐Ÿ‡ง EN
๐Ÿซ’

HermesJS ๐Ÿซ’๐ŸŒฟ

Reliable messaging for Node.js / TypeScript. Hermes PostgreSQL (logical replication) & Hermes MongoDB (change streams) implement the Outbox pattern โ€” span a DB transaction over persisting an entity and publishing a message. A library, not a framework.

Docs >>