Mapping Types and Decorators in TypeScript
Transforming Types with Mapping Types and Enriching Code with Decorators in Typescript
In a previous blog post, we explored the powerful combination of OpenAPI and NestJS, delving into their capabilities within the NestJS framework.
Let's take a look at each component and how they work together: OpenAI, NestJS, and Mapped Types.
OpenAI: OpenAI developed GPT models, capable of understanding and generating human-like text, for natural language processing tasks like text generation, translation, and content summarization.
NestJS: NestJS is a TypeScript-based backend framework for efficient, scalable, and maintainable server-side applications, built on Node.js and inspired by Angular. It supports structured, organized applications like APIs and microservices.
For a comprehensive walkthrough, please refer to the previous post.
Mapped types are a TypeScript feature that allows you to modify and control a type's attributes. They are used to generate new kinds from existing types, frequently by altering or converting specific attributes.
Step by Step Mapped Types in TypeScript
Step 1: Create a NestJS Project
If you haven't already, install Node.js and npm (Node Package Manager).
Create a new NestJS project: nest new my-openai-app
Step 2: Add Dependencies
Go to your project directory by typing cd my-openai-app.
Install the necessary dependencies by running npm install axios @nestjs/common @nestjs/core.
Step 3: Develop an OpenAI Service
Create a new service file, such as openai.service.ts, within the source code of your project.
To perform HTTP calls to the OpenAI, use the axios library.
Define techniques for communicating with the OpenAI API, such as text creation via submitting text.
//openai.service.ts
import { Injectable } from '@nestjs/common';
import axios from 'axios';
@Injectable()
export class OpenAiService {
private openAiApiUrl = 'https://api.openai.com/v1';
async generateText(prompt: string): Promise<string> {
const response = await axios.post(`${this.openAiApiUrl}/engines/davinci-codex/completions`, {
prompt,
max_tokens: 50,
}, {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_OPENAI_API_KEY',
},
});
return response.data.choices[0]?.text || '';
}
}
Step 4: Create a new controller file
Make a new controller file, such as app.controller.ts.
Import the OpenAiService into the controller
Create an API endpoint that generates text using the OpenAI service.
//app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { OpenAiService } from './openai.service';
@Controller()
export class AppController {
constructor(private readonly openAiService: OpenAiService) {}
@Get('generate-text')
async generateText(): Promise<string> {
const prompt = 'Once upon a time';
const generatedText = await this.openAiService.generateText(prompt);
return generatedText;
}
}
Step 5: Start your NestJS application
Run Your NestJS Application npm run start:dev.
In your browser or API tool, navigate to the created text endpoint:
This example showcases using OpenApi's capabilities in a NestJS application, using an OpenAi service and controller to generate text based on a prompt. Adjust to suit use case, handle error cases, and follows security best practices.
Decorators in TypeScript:
Decorators are TypeScript feature that allows you to annotate classes, methods, properties, and parameters throughout the design process. They make it possible to add metadata or behavior to your code in a clean and modular fashion.
Step-by-Step Decorators in TypeScript
Step 1: Create a NestJS Project
If you haven't already, install Node.js and npm (Node Package Manager).
Create a new NestJS project: nest new my-openai-app
Step 2: Add Dependencies
Go to your project directory by typing cd my-openai-app.
Install the necessary dependencies by running npm install axios @nestjs/common @nestjs/core.
Step 3: Create a New Decorator File
Create a new decorator file within your project's source code, such as decorators/openai.decorator.ts.
Create a custom decorator that will be used to identify methods that need OpenAI text creation.
//openai.decorator.ts
import { SetMetadata } from '@nestjs/common';
export const OpenAiGeneratedText = (prompt: string) => SetMetadata('openAiPrompt', prompt);
Step 4: Create a New Interceptor File
Create an OpenAI Interceptor interceptors/openai.interceptor.ts.
Extract the OpenAi prompt from the custom decorator and contact the OpenAi service to create text in this interceptor.
//openai.interceptor.ts import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { OpenAiService } from '../openai.service'; @Injectable() export class OpenAiInterceptor implements NestInterceptor { constructor(private readonly openAiService: OpenAiService) {} intercept(context: ExecutionContext, next: CallHandler): Observable<any> { const prompt = Reflect.getMetadata('openAiPrompt', context.getHandler()); return next.handle().pipe( map(async (data) => { const generatedText = await this.openAiService.generateText(prompt); return { ...data, generatedText }; }), ); } }
Step 5: Import and Use the Custom Decorator along with the OpenAI Interceptor
Import and utilize the custom decorator along with the OpenAI interceptor in
your controller to create text for particular methods.
//app.controller.ts
import { Controller, Get, UseInterceptors } from '@nestjs/common';
import { OpenAiGeneratedText } from './decorators/openai.decorator';
import { OpenAiInterceptor } from './interceptors/openai.interceptor';
@Controller()
export class AppController {
@Get('story')
@UseInterceptors(OpenAiInterceptor)
@OpenAiGeneratedText('Once upon a time')
async getStory(): Promise<any> {
return { message: 'Story retrieved successfully' };
}
}
Step 6: Start your NestJS Application
Begin your NestJS application by typing: npm run start:dev.
In your browser or API tool, navigate to the produced narrative endpoint: localhost:3000/story.
Mapping Types and Decorators in TypeScript investigates the use of OpenAI and NestJS to develop server-side apps. Decorators provide metadata or behavior to your code, whereas mapped types change existing types. The article walks you through the process of integrating OpenAI text creation into a NestJS application using custom decorators and interceptors.
to be continued...