I'm creating a Node.js api using Typebox, and I'm struggling with some types, specifically Dates and ObjectIds. I created a Transform for IsoDates and ObjectIds using the following...
export const TypeboxIsoDate = Type.Transform(Type.String({ format: 'date-time' }))
.Decode(value => new Date(value))
.Encode(value => value.toISOString());
export const TypeboxObjectId = Type.Transform(Type.String({ format: 'objectId' }))
.Decode(value => {
// When coming from string (like JSON), convert to ObjectId
// For TypeBox transformers, value should always be a string during Decode
return new ObjectId(value as string);
})
.Encode(value => {
// When serializing, convert ObjectId to string
// Handle the case where value might already be a string
if (typeof value === 'string') return value;
// Use toString() for ObjectId or any object with toString method
return (value as any).toString();;
});
Here is my schema definition for a product...
export const ProductSchema = Type.Object({
_id: TypeboxObjectId,
name: Type.String({
title: 'Name'
}),
description: Type.Optional(Type.String({
title: 'Description'
})),
price: Money({
minimum: 0,
title: 'Price'
}),
quantity: Type.Number({
minimum: 0,
title: 'Quantity'
}),
someDate: TypeboxIsoDate
});
When I post the following json to the POST of my /products endpoint...
{
"name": "Widget",
"description": "It is a Widget",
"price": 39.99,
"quantity": 7,
"someDate": "2025-03-25T18:18:56.000Z"
}
This is what gets returned in the response...
{
"name": "Widget",
"description": "It is a Widget",
"price": 39.99,
"quantity": 7,
"someDate": "2025-03-25T18:18:56.000Z",
"_id": {
"buffer": {
"type": "Buffer",
"data": [
103,
234,
201,
39,
112,
235,
139,
42,
63,
1,
179,
14
]
}
},
"_created": "2025-03-31T16:56:07.040Z",
"_createdBy": "system",
"_updated": "2025-03-31T16:56:07.040Z",
"_updatedBy": "system"
}
So... that _id is really weird, but it seems to be ok in MongoDb. Also, in MongoDb, someDate is just a string, but _created and _updated are actual ISODates. I auto-created those fields as Dates before saving, but the incoming someDate property never gets converted to an actual Date. Here is what the document looks like in MongoDb...
{
"_id" : ObjectId("67eac843bc800a699734da58"),
"name" : "Doohicky",
"description" : "It is a Doohicky",
"price" : 39.99,
"quantity" : NumberInt(7),
"someDate" : "2025-03-25T18:18:56.000Z",
"_created" : ISODate("2025-03-31T16:52:19.792+0000"),
"_createdBy" : "system",
"_updated" : ISODate("2025-03-31T16:52:19.792+0000"),
"_updatedBy" : "system"
}
What I want is for these fields to generate actual ObjectIds and ISODates in Mongodb, ObjectIds and Dates in javascript, and also generate proper json-schema - { "type": "string", "format": "objectId" } and { "type": "string", "format": "date-time" }, respectively. I'm actually not sure about that json-schema for ObjectId, but I am very sure about the json-schema for date-time.
Any help will be greatly appreciated.