Mapping Types and Decorators in TypeScript

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:

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).

  • Install NestJS CLI globally: npm install -g @nestjs/cli.

  • 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

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).

  • Install NestJS CLI globally: npm install -g @nestjs/cli.

  • 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.

💡
Custom decorators and interceptors integrate OpenAI's text generation into the NestJS application, marking methods with desired prompts and automatically generating text. Real-world scenarios may require additional considerations for error handling, security, and optimization.

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...

Summary
Finally, Mapped Types and Decorators in TypeScript allow developers to use the NestJS framework to construct fast, scalable, and maintainable server-side applications. By using OpenAI's text-generating capabilities, you may improve the functionality of your application while keeping a clean and modular codebase. In real-world settings, keep error management, security, and optimization in mind.