Typescript - convertir el tipo de ObjectId de mongoose a cadena al compartir entre backend y frontend
Estoy intentando crear algunos tipos basados en modelos de esquema de mongo y compartirlos con el front-end en un mono repositorio.
Tipo de ejemplo:
import { Types } from "mongoose";
export interface Profile {
userId: Types.ObjectId;
education: {
university: Types.ObjectId;
};
}
Mi esquema de perfil usa esta interfaz de Perfil para definir tipos y la misma interfaz se usa en el front-end. Dado que el front-end no necesita conocer los tipos de mongoose, me gustaría tener userId y education.university como cadena. Por cierto, cuando obtengo la respuesta de la API desde el servidor en el front-end, recibo estos valores solo como cadenas.
He probado un mapeador de TS tal como se define maravillosamente aquí. Esto resolvió mi problema parcialmente: puedo ver que userId se convierte en cadena en el front-end. Pero esto no resuelve el objeto anidado education. Puedo definir education como un tipo separado y usar el mapeador, pero creo que esta no es una forma escalable. Me gustaría que el mapeador manejara la conversión de tipos de los tipos anidados también.
typeMapper.tsimport { Types } from "mongoose";
type MapObjectIdToString<PropType> = PropType extends Types.ObjectId
? string
: PropType;
export type MapDbObject<T> = {
[PropertyKey in keyof T]: MapObjectIdToString<T[PropertyKey]>;
};
Estoy convirtiendo el tipo Profile de esta manera
export type UiProfile = MapDbObject<Profile>; // here `userId` is string, but `university` is still Types.ObjectId
¿Hay alguna manera de actualizar mi TS Mapper para convertir todos los campos, incluidos los campos dentro de objetos anidados, de Types.ObjectId a string? Gracias de antemano.
Respuesta #1
Un tipo recursivo lo hará:
type StringIds<T> = T extends Types.ObjectId ? string : T extends Record<any, any> ? {
[K in keyof T]: StringIds<T[K]>;
} : T;
También funciona con arrays. Pruébalo tú mismo a continuación:
Parque infantil
