0% found this document useful (0 votes)
41 views

Make Nodejs API S Great With TypeScript Dmytro Zharkov

- Typescript can help address issues with NodeJS APIs like lack of strong typing, documentation, and REST design by providing features like interfaces, classes, decorators, and generics. - These features allow for better modeling of data, validation, documentation, and structure compared to plain JavaScript. - Examples demonstrate how to add request validation, declarative routes, and HATEOAS with hypermedia using Typescript. - Decorators can also automate documentation generation through libraries like TSOA.

Uploaded by

Mauro Sosa
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views

Make Nodejs API S Great With TypeScript Dmytro Zharkov

- Typescript can help address issues with NodeJS APIs like lack of strong typing, documentation, and REST design by providing features like interfaces, classes, decorators, and generics. - These features allow for better modeling of data, validation, documentation, and structure compared to plain JavaScript. - Examples demonstrate how to add request validation, declarative routes, and HATEOAS with hypermedia using Typescript. - Decorators can also automate documentation generation through libraries like TSOA.

Uploaded by

Mauro Sosa
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 29

MAKE NODEJS APIs GREAT WITH TYPESCRIPT

ABOUT ME

I really like my work, software engineering


never makes me bored, always keeps in
learning and improving mood.

[email protected]

http://bit.ly/2FAm3Lr

http://bit.ly/2FAm3Lr
NODEJS REPUTATION

FRONT-END DEVELOPERS

NodeJS
What’s wrong with NodeJS APIs?

● Dynamic VS strong typing

● Pure OOP model of JS


● No of access modifiers

● No hypermedia in RESTful APIs


● Lack of documentation
● Design and structure

4
TYPESCRIPT FOR A RESQUE

TYPE SYSTEM INTERFACES

DECORATORS ACCESS MODIFIERS

GENERICS ABSTRACT CLASSES


TYPES TRIPLET

TYPE ALIASES
public port: number;

INTERFACES
protected server: http.Server;

CLASSES
public article: Article;
LET’S COMPARE

TYPE ALISES INTERFACES


● Primitive types (number, string, ● Reference types only
boolean) and reference types (Object). ● Can be extended
● Can’t be extended ● Signature not implementation

CLASSES
● Reference types only
● Can be extended
● Signature and implementation
INTERFACES

interface BaseArticle {
SKU: string, interface FashionArticle extends BaseArticle {
name: string, size: Sizes,
type: string, color: Colors
price: Price }
}
export default FashionArticle;
export default BaseArticle;

import { Document } from "mongoose";

interface FashionArticleModel extends FashionArticle, Document {};


export default FashionArticleModel;
USING INTERFACES AND GENERICS

import { Schema, Model, model} from "mongoose";


import FashionArticleModel from "../interfaces/FashionArticleModel";

const ArticleSchema: Schema = new Schema({


….
});

const ArticleModel: Model<FashionArticleModel> =


model<FashionArticleModel>("Article", ArticleSchema);

export {ArticleModel};
MORE INTERFACES

export class Server {

protected app: express.Application;

protected server: http.Server;

private db: mongoose.Connection;

private routes: express.Router[] = [];

}
ACCESS MODIFIERS

PUBLIC
Default modifier and can be omitted
(better not).

PRIVATE
Restics members visibility to current
class only.

PROTECTED
Visible in derived classes.
IN PRACTICE

class Server {
import * as io from "socket.io";
protected app: express.Application;
protected server: http.Server;
class SocketServer extends Server {
public port: number;
private socketServer: io.Server;
constructor(port: number = 3000) {
constructor(public port: number) {
this.app = express();
super(port);
this.port = port;
this.socketServer = io(this.server);
this.app.set("port", port);
….
this.app.listen(this.port);
}
}
}
}
DECORATORS

CLASSES METHODS

PARAMETERS FIELDS
EXAMPLE: TRY-CATCH WRAPPER

class TestClass {

@safe
public doSomething(str: string): boolean {
return str.length > 0;
}

var safeTest: TestClass = new TestClass();


safeTest.doSomething(null);
safeTest.doSomething("Hello from IJS and API conference");
EXAMPLE: TRY-CATCH WRAPPER

function safe(target: any, propertyKey: string, descriptor:


TypedPropertyDescriptor<any>): TypedPropertyDescriptor<any> {

let originalMethod = descriptor.value;


descriptor.value = function () {
try {
originalMethod.apply(this, arguments);
} catch(ex) {
console.error(ex);
}
};

return descriptor;
}
EXAMPLE: DECLARATIVE ROUTES

Typical ExpressJS route:

var express = require('express');


var router = express.Router();

router.get('/', function(req, res, next) {


res.send('respond with a resource');
});

router.get('/:id', function(req, res, next) {


res.send('respond with a resource');
});
EXAMPLE: DECLARATIVE ROUTES
@RouteHandler("/sample-route")
class SampleRoute {
public router: Router;
constructor(public app: Server) {}

@Get()
public resources(req: Request, res: Response) {
res.json([]);
}

@Get("/:id")
public resources(req: Request, res: Response) {
res.json({});
}
}
EXAMPLE: REQUEST VALIDATION

@Validate({
param: "name",
validate: "required"
})
public createArticle(request: Request, response: Response): void {
// create an article
}
EXAMPLE: REQUEST VALIDATION

export function Validate(params: Array<any>): any {


return (target: Object, propertyKey: string): TypedPropertyDescriptor<any> => {

const descriptor = Object.getOwnPropertyDescriptor(target, propertyKey);


const originalMethod = descriptor.value;

descriptor.value = function () {
const body = arguments[0].body;
const response = arguments[1];
// do some work
};
return descriptor;
};
}
EXAMPLE: HATEOAS

Hypermedia allows to decouple client


and server to a large extent and allow
them to evolve independently.
EXAMPLE: HYPERMEDIA

DEMO
DOCUMENTATION

TSOA
AUTO SWAGGER DOCUMENTATION WITH DECORATORS

TSOA
@Route("Users")
class ArticlesService {

@Post()
public createArticle(@Body() requestBody: FashionArticle): Promise<FashionArticle> {
// create an article
}
}

export default ArticlesService;


AUTO SWAGGER DOCS WITH DECORATORS
UNIT AND INTEGRATION TESTS
WRITE YOUR TESTS IN TYPESCRIPT

SUPERTEST
DEBUG DIRECTLY IN TS
DRAWBACKS
Additional build step.

Lack of definition files for


npm modules.

Source and compiled code.


MAKE NODEJS APIs GREAT WITH TYPESCRIPT
THANKS FOR ATTENTION

Slides
NodeJS TypeScript starter http://bit.ly/2FW64qn
TSOA auto swagger documentation http://bit.ly/2FW64qn

You might also like