- Types make sure the code doesn't have basic bugs and makes it easy to refactor the code.
- Types make sure that the code is self-documented.
- Never use the type
anyin the code. - When ever we have multiple string values which we compare, always use enum. Create the enum in the
typesfolder. We keep it string in the database, but in the code we use enum. Keeping it string in Database allows more flexibility.
- Earlier we used to use
graphqltypes, but now we are not usinggraphqlso we should not usegraphqltypes.
- We use
prismawhich generates types for us. We should use those in the API code, when saving or fetching data from the database. - However when we return the data to the front end, we should not use the
prismatypes. We should create our own types. This helps in decoupling the prisma from the front end code. - We can use a
Dtoobject very similar to the prisma type. Then thisDtoobject can be used on the frontend. Seeacademy-ui/src/types/html-captures/ClickableDemoHtmlCaptureDto.tsfor an example. - If you see
academy-ui/src/app/api/[spaceId]/html-captures/route.tswe don't need to convert theprismatype toDtoobject, because we both have the exact same structure. - We should not try to use nesting in the types. We should keep the types flat. Like in the above case we just return
the
ClickableDemoHtmlCaptureDtorather than something like{capture: ClickableDemoHtmlCaptureDto}.
- When creating a new object, there is no need to pass the id. The
idcan be calculated by the server. - For some cases when we have
upserti.e. create and update as the same request, then we can pass theidin the request. But in most cases we don't need to pass theidin the request for creating a new object. idcan be created using the functioncreateNewEntityIddeclared inshared/web-core/src/utils/space/createNewEntityId.ts.- May be we include part of spaceId in the
idas well. This is to make sure that theidis unique across all spaces. - If the request is not same as Dto, then we should create a new type for the request in the
types/requestfolder.
NOTE: There is no need to use graphql types now. Create types explicitly
In our project, defining clear request and response types is essential for maintaining type safety and improving code readability. This practice helps ensure that our API interactions are consistent and manageable.
-
Create Type Definitions: For each request and response type, create an interface within the appropriate
typesfolder. Specifically, place request interfaces in therequestfolder and response interfaces in theresponsefolder. This organization promotes clarity and easy access to type definitions. -
Example Usage: Below are examples of request and response types for deleting a item. These interfaces define the expected structure of the API interactions.
Response Type
Usage Example
import { withErrorHandlingV2 } from '@dodao/web-core/api/helpers/middlewares/withErrorHandling';
async function postHandler(req: NextRequest, context: { params: Promise<{ spaceId: string }> }) {
const { spaceId } = await context.params;
// ... handle request logic ...
return capture;
}
export const POST = withErrorHandlingV2(postHandler);- Make sure to use strict types for request and response.
- In Next.js 15+, route handler params must be typed as
Promise<>and awaited. - Use
withErrorHandlingV2from@dodao/web-corefor all API routes. Do not use the olderwithErrorHandlingorwithErrorHandlingV1middlewares.