Express.jsã¢ããªã±ãŒã·ã§ã³ã§TypeScriptããã«ãŠã§ã¢ãçè§£ããå®è£ ããããã®å æ¬çãªã¬ã€ããå ç¢ã§ä¿å®å¯èœãªã³ãŒãã®ããã®é«åºŠãªã¿ã€ããã¿ãŒã³ãæ¢æ±ããŸãã
TypeScriptããã«ãŠã§ã¢ïŒExpressããã«ãŠã§ã¢ã®ã¿ã€ããã¿ãŒã³ããã¹ã¿ãŒãã
Express.jsã¯ãããããªã¹ãã§æè»ãªNode.jsã®Webã¢ããªã±ãŒã·ã§ã³ãã¬ãŒã ã¯ãŒã¯ã§ãããéçºè ã¯å ç¢ã§ã¹ã±ãŒã©ãã«ãªAPIãšWebã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããŸããTypeScriptã¯éçåä»ãã远å ããããšã§Expressã匷åããã³ãŒãã®ä¿å®æ§ãåäžããããšã©ãŒãæ©æã«æ€åºããŸããããã«ãŠã§ã¢é¢æ°ã¯Expressã®åºç€ã§ãããã«ãŒããã³ãã©ãŒã«å°éããåã«ãªã¯ãšã¹ããã€ã³ã¿ãŒã»ããããŠåŠçã§ããŸãããã®èšäºã§ã¯ãExpressããã«ãŠã§ã¢ãå®çŸ©ããã³å©çšããããã®é«åºŠãªTypeScriptã¿ã€ããã¿ãŒã³ãæ¢æ±ããã¿ã€ãå®å šæ§ãšã³ãŒãã®æçããåäžãããŸãã
Expressããã«ãŠã§ã¢ã®çè§£
ããã«ãŠã§ã¢é¢æ°ã¯ããªã¯ãšã¹ããªããžã§ã¯ãïŒreqïŒãã¬ã¹ãã³ã¹ãªããžã§ã¯ãïŒresïŒãããã³ã¢ããªã±ãŒã·ã§ã³ã®ãªã¯ãšã¹ã/ã¬ã¹ãã³ã¹ãµã€ã¯ã«å
ã®æ¬¡ã®ããã«ãŠã§ã¢é¢æ°ã«ã¢ã¯ã»ã¹ã§ãã颿°ã§ããããã«ãŠã§ã¢é¢æ°ã¯ã次ã®ã¿ã¹ã¯ãå®è¡ã§ããŸãã
- ä»»æã®ã³ãŒããå®è¡ããã
- ãªã¯ãšã¹ããªããžã§ã¯ããšã¬ã¹ãã³ã¹ãªããžã§ã¯ãã倿Žããã
- ãªã¯ãšã¹ã/ã¬ã¹ãã³ã¹ãµã€ã¯ã«ãçµäºããã
- ã¹ã¿ãã¯å ã®æ¬¡ã®ããã«ãŠã§ã¢é¢æ°ãåŒã³åºãã
ããã«ãŠã§ã¢é¢æ°ã¯ãExpressã¢ããªã±ãŒã·ã§ã³ã«è¿œå ããããšãé çªã«å®è¡ãããŸããããã«ãŠã§ã¢ã®äžè¬çãªãŠãŒã¹ã±ãŒã¹ã¯æ¬¡ã®ãšããã§ãã
- ãªã¯ãšã¹ãã®ãã°èšé²ã
- ãŠãŒã¶ãŒã®èªèšŒã
- ãªãœãŒã¹ãžã®ã¢ã¯ã»ã¹æš©ã®èªå¯ã
- ãªã¯ãšã¹ãããŒã¿ã®æ€èšŒã
- ãšã©ãŒåŠçã
åºæ¬çãªTypeScriptããã«ãŠã§ã¢
åºæ¬çãªTypeScript Expressã¢ããªã±ãŒã·ã§ã³ã§ã¯ãããã«ãŠã§ã¢é¢æ°ã¯æ¬¡ã®ããã«ãªããŸãã
import { Request, Response, NextFunction } from 'express';
function loggerMiddleware(req: Request, res: Response, next: NextFunction) {
console.log(`Request: ${req.method} ${req.url}`);
next();
}
export default loggerMiddleware;
ãã®ã·ã³ãã«ãªããã«ãŠã§ã¢ã¯ããªã¯ãšã¹ãã¡ãœãããšURLãã³ã³ãœãŒã«ã«èšé²ããŸããã¿ã€ãã¢ãããŒã·ã§ã³ãåè§£ããŠã¿ãŸãããã
RequestïŒExpressãªã¯ãšã¹ããªããžã§ã¯ãã衚ããŸããResponseïŒExpressã¬ã¹ãã³ã¹ãªããžã§ã¯ãã衚ããŸããNextFunctionïŒåŒã³åºããããšãã¹ã¿ãã¯å ã®æ¬¡ã®ããã«ãŠã§ã¢ãå®è¡ãã颿°ã
ãã®ããã«ãŠã§ã¢ã¯ãExpressã¢ããªã±ãŒã·ã§ã³ã§æ¬¡ã®ããã«äœ¿çšã§ããŸãã
import express from 'express';
import loggerMiddleware from './middleware/loggerMiddleware';
const app = express();
const port = 3000;
app.use(loggerMiddleware);
app.get('/', (req, res) => {
res.send('Hello, world!');
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
ããã«ãŠã§ã¢ã®é«åºŠãªã¿ã€ããã¿ãŒã³
åºæ¬çãªããã«ãŠã§ã¢ã®äŸã¯æ©èœããŸãããããè€éãªã·ããªãªã§ã¯æè»æ§ãšã¿ã€ãå®å šæ§ãäžè¶³ããŠããŸããTypeScriptã䜿çšããããã«ãŠã§ã¢éçºã匷åããé«åºŠãªã¿ã€ããã¿ãŒã³ãæ¢æ±ããŸãããã
1. ã«ã¹ã¿ã ãªã¯ãšã¹ã/ã¬ã¹ãã³ã¹ã¿ã€ã
å€ãã®å ŽåãRequestãŸãã¯Responseãªããžã§ã¯ããã«ã¹ã¿ã ããããã£ã§æ¡åŒµããå¿
èŠããããŸããããšãã°ãèªèšŒåŸãRequestãªããžã§ã¯ãã«userããããã£ã远å ããå ŽåããããŸããTypeScriptã§ã¯ã宣èšã®ããŒãžã䜿çšããŠæ¢åã®ã¿ã€ããæ¡åŒµã§ããŸãã
// src/types/express/index.d.ts
import { Request as ExpressRequest } from 'express';
declare global {
namespace Express {
interface Request {
user?: {
id: string;
email: string;
// ... other user properties
};
}
}
}
export {}; // This is needed to make the file a module
ãã®äŸã§ã¯ããªãã·ã§ã³ã®userããããã£ãå«ããããã«Express.Requestã€ã³ã¿ãŒãã§ã€ã¹ãæ¡åŒµããŠããŸããèªèšŒããã«ãŠã§ã¢ã§ããã®ããããã£ãèšå®ã§ããŸãã
import { Request, Response, NextFunction } from 'express';
function authenticationMiddleware(req: Request, res: Response, next: NextFunction) {
// Simulate authentication logic
const userId = req.headers['x-user-id'] as string; // Or fetch from a token, etc.
if (userId) {
// In a real application, you would fetch the user from a database
req.user = {
id: userId,
email: `user${userId}@example.com`
};
next();
} else {
res.status(401).send('Unauthorized');
}
}
export default authenticationMiddleware;
ã«ãŒããã³ãã©ãŒã§ãreq.userããããã£ã«å®å
šã«ã¢ã¯ã»ã¹ã§ããŸãã
import express from 'express';
import authenticationMiddleware from './middleware/authenticationMiddleware';
const app = express();
const port = 3000;
app.use(authenticationMiddleware);
app.get('/profile', (req: Request, res: Response) => {
if (req.user) {
res.send(`Hello, ${req.user.email}! Your user ID is ${req.user.id}`);
} else {
// This should never happen if the middleware is working correctly
res.status(500).send('Internal Server Error');
}
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
2. ããã«ãŠã§ã¢ãã¡ã¯ããª
ããã«ãŠã§ã¢ãã¡ã¯ããªã¯ãããã«ãŠã§ã¢é¢æ°ãè¿ã颿°ã§ãããã®ãã¿ãŒã³ã¯ãç¹å®ã®ãªãã·ã§ã³ãŸãã¯äŸåé¢ä¿ã§ããã«ãŠã§ã¢ãæ§æããå¿ èŠãããå Žåã«åœ¹ç«ã¡ãŸããããšãã°ãã¡ãã»ãŒãžãç¹å®ã®ãã¡ã€ã«ã«èšé²ãããã®ã³ã°ããã«ãŠã§ã¢ãèããŠã¿ãŸãããã
import { Request, Response, NextFunction } from 'express';
import fs from 'fs';
import path from 'path';
function createLoggingMiddleware(logFilePath: string) {
return (req: Request, res: Response, next: NextFunction) => {
const logMessage = `[${new Date().toISOString()}] Request: ${req.method} ${req.url}\n`;
fs.appendFile(logFilePath, logMessage, (err) => {
if (err) {
console.error('Error writing to log file:', err);
}
next();
});
};
}
export default createLoggingMiddleware;
ãã®ããã«ãŠã§ã¢ãã¡ã¯ããªã¯æ¬¡ã®ããã«äœ¿çšã§ããŸãã
import express from 'express';
import createLoggingMiddleware from './middleware/loggingMiddleware';
const app = express();
const port = 3000;
const logFilePath = path.join(__dirname, 'logs', 'requests.log');
app.use(createLoggingMiddleware(logFilePath));
app.get('/', (req, res) => {
res.send('Hello, world!');
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
3. éåæããã«ãŠã§ã¢
ããã«ãŠã§ã¢é¢æ°ã¯ãããŒã¿ããŒã¹ã¯ãšãªãAPIåŒã³åºããªã©ã®éåææäœãå®è¡ããå¿
èŠãããããšããããããŸããéåææäœãæ£ããåŠçããã«ã¯ãéåææäœã®å®äºåŸã«next颿°ãåŒã³åºãããããã«ããå¿
èŠããããŸããããã¯ãasync/awaitãŸãã¯Promiseã䜿çšããŠå®çŸã§ããŸãã
import { Request, Response, NextFunction } from 'express';
async function asyncMiddleware(req: Request, res: Response, next: NextFunction) {
try {
// Simulate an asynchronous operation
await new Promise(resolve => setTimeout(resolve, 100));
console.log('Asynchronous operation completed');
next();
} catch (error) {
next(error); // Pass the error to the error handling middleware
}
}
export default asyncMiddleware;
éèŠïŒéåæããã«ãŠã§ã¢å
ã§ãšã©ãŒãåŠçããnext(error)ã䜿çšããŠãšã©ãŒåŠçããã«ãŠã§ã¢ã«æž¡ãããšãå¿ããªãã§ãã ãããããã«ããããšã©ãŒãé©åã«åŠçããã³èšé²ãããŸãã
4. ãšã©ãŒåŠçããã«ãŠã§ã¢
ãšã©ãŒåŠçããã«ãŠã§ã¢ã¯ããªã¯ãšã¹ã/ã¬ã¹ãã³ã¹ãµã€ã¯ã«äžã«çºçãããšã©ãŒãåŠçããç¹å¥ãªã¿ã€ãã®ããã«ãŠã§ã¢ã§ãããšã©ãŒåŠçããã«ãŠã§ã¢é¢æ°ã«ã¯ã4ã€ã®åŒæ°ïŒerrãreqãresãããã³nextïŒããããŸãã
import { Request, Response, NextFunction } from 'express';
function errorHandler(err: any, req: Request, res: Response, next: NextFunction) {
console.error(err.stack);
res.status(500).send('Something went wrong!');
}
export default errorHandler;
ãšã©ãŒåŠçããã«ãŠã§ã¢ã¯ãä»ã®ãã¹ãŠã®ããã«ãŠã§ã¢ããã³ã«ãŒããã³ãã©ãŒã®åŸã«ç»é²ããå¿ èŠããããŸããExpressã¯ã4ã€ã®åŒæ°ã®ååšã«ãã£ãŠãšã©ãŒåŠçããã«ãŠã§ã¢ãèå¥ããŸãã
import express from 'express';
import asyncMiddleware from './middleware/asyncMiddleware';
import errorHandler from './middleware/errorHandler';
const app = express();
const port = 3000;
app.use(asyncMiddleware);
app.get('/', (req, res) => {
throw new Error('Simulated error!'); // Simulate an error
});
app.use(errorHandler); // Error handling middleware MUST be registered last
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
5. ãªã¯ãšã¹ãæ€èšŒããã«ãŠã§ã¢
ãªã¯ãšã¹ãæ€èšŒã¯ãå®å
šã§ä¿¡é Œæ§ã®é«ãAPIãæ§ç¯ããäžã§éèŠãªåŽé¢ã§ããããã«ãŠã§ã¢ã䜿çšããŠãåä¿¡ãªã¯ãšã¹ãããŒã¿ãæ€èšŒããã«ãŒããã³ãã©ãŒã«å°éããåã«ç¹å®ã®åºæºãæºãããŠããããšã確èªã§ããŸããjoiãŸãã¯express-validatorã®ãããªã©ã€ãã©ãªããªã¯ãšã¹ãæ€èšŒã«äœ¿çšã§ããŸãã
express-validatorã䜿çšããäŸã次ã«ç€ºããŸãã
import { Request, Response, NextFunction } from 'express';
import { body, validationResult } from 'express-validator';
const validateCreateUserRequest = [
body('email').isEmail().normalizeEmail(),
body('password').isLength({ min: 8 }),
(req: Request, res: Response, next: NextFunction) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
next();
}
];
export default validateCreateUserRequest;
ãã®ããã«ãŠã§ã¢ã¯ããªã¯ãšã¹ãããã£ã®emailãã£ãŒã«ããšpasswordãã£ãŒã«ããæ€èšŒããŸããæ€èšŒã«å€±æããå Žåããšã©ãŒã¡ãã»ãŒãžã®é
åãå«ã400 Bad Requestã¬ã¹ãã³ã¹ãè¿ããŸãããã®ããã«ãŠã§ã¢ã¯ãã«ãŒããã³ãã©ãŒã§æ¬¡ã®ããã«äœ¿çšã§ããŸãã
import express from 'express';
import validateCreateUserRequest from './middleware/validateCreateUserRequest';
const app = express();
const port = 3000;
app.post('/users', validateCreateUserRequest, (req, res) => {
// If validation passes, create the user
res.send('User created successfully!');
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
6. ããã«ãŠã§ã¢ã®äŸåæ§æ³šå ¥
ããã«ãŠã§ã¢é¢æ°ãå€éšãµãŒãã¹ãŸãã¯æ§æã«äŸåããŠããå ŽåãäŸåæ§æ³šå
¥ã¯ãã¹ãå®¹ææ§ãšä¿å®æ§ãåäžãããã®ã«åœ¹ç«ã¡ãŸããtsyringeã®ãããªäŸåæ§æ³šå
¥ã³ã³ããã䜿çšããããäŸåé¢ä¿ãåŒæ°ãšããŠããã«ãŠã§ã¢ãã¡ã¯ããªã«æž¡ãããšãã§ããŸãã
äŸåæ§æ³šå ¥ã䜿çšããããã«ãŠã§ã¢ãã¡ã¯ããªã®äŸã次ã«ç€ºããŸãã
// src/services/UserService.ts
export class UserService {
async createUser(email: string, password: string): Promise {
// In a real application, you would save the user to a database
console.log(`Creating user with email: ${email} and password: ${password}`);
await new Promise(resolve => setTimeout(resolve, 500)); // Simulate a database operation
}
}
// src/middleware/createUserMiddleware.ts
import { Request, Response, NextFunction } from 'express';
import { UserService } from '../services/UserService';
function createCreateUserMiddleware(userService: UserService) {
return async (req: Request, res: Response, next: NextFunction) => {
try {
const { email, password } = req.body;
await userService.createUser(email, password);
res.status(201).send('User created successfully!');
} catch (error) {
next(error);
}
};
}
export default createCreateUserMiddleware;
// src/app.ts
import express from 'express';
import createCreateUserMiddleware from './middleware/createUserMiddleware';
import { UserService } from './services/UserService';
import errorHandler from './middleware/errorHandler';
const app = express();
const port = 3000;
app.use(express.json()); // Parse JSON request bodies
const userService = new UserService();
const createUserMiddleware = createCreateUserMiddleware(userService);
app.post('/users', createUserMiddleware);
app.use(errorHandler);
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
TypeScriptããã«ãŠã§ã¢ã®ãã¹ããã©ã¯ãã£ã¹
- ããã«ãŠã§ã¢é¢æ°ãå°ãããçŠç¹ãçµã£ãŠç¶æããŸããåããã«ãŠã§ã¢é¢æ°ã¯ãåäžã®è²¬ä»»ãæã€å¿ èŠããããŸãã
- ããã«ãŠã§ã¢é¢æ°ã«ããããããååã䜿çšããŸããååã¯ãããã«ãŠã§ã¢ãè¡ãããšãæç¢ºã«ç€ºãå¿ èŠããããŸãã
- ãšã©ãŒãé©åã«åŠçããŸããåžžã«ãšã©ãŒããã£ãããã
next(error)ã䜿çšããŠãšã©ãŒåŠçããã«ãŠã§ã¢ã«æž¡ããŸãã - ã«ã¹ã¿ã ãªã¯ãšã¹ã/ã¬ã¹ãã³ã¹ã¿ã€ãã䜿çšããŠãã¿ã€ãå®å
šæ§ã匷åããŸããå¿
èŠã«å¿ããŠã
Requestã€ã³ã¿ãŒãã§ã€ã¹ãšResponseã€ã³ã¿ãŒãã§ã€ã¹ãã«ã¹ã¿ã ããããã£ã§æ¡åŒµããŸãã - ããã«ãŠã§ã¢ãã¡ã¯ããªã䜿çšããŠãç¹å®ã®ãªãã·ã§ã³ã§ããã«ãŠã§ã¢ãæ§æããŸãã
- ããã«ãŠã§ã¢é¢æ°ãããã¥ã¡ã³ãåããŸããããã«ãŠã§ã¢ãè¡ãããšãšãã®äœ¿ç𿹿³ã説æããŸãã
- ããã«ãŠã§ã¢é¢æ°ã培åºçã«ãã¹ãããŸããããã«ãŠã§ã¢é¢æ°ãæ£ããæ©èœããŠããããšã確èªããããã«ããŠããããã¹ããäœæããŸãã
çµè«
TypeScriptã¯ãéçåä»ãã远å ããã³ãŒãã®ä¿å®æ§ãåäžããããšã©ãŒãæ©æã«æ€åºããããšã«ãããExpressããã«ãŠã§ã¢ã®éçºãå€§å¹ ã«åŒ·åããŸããã«ã¹ã¿ã ãªã¯ãšã¹ã/ã¬ã¹ãã³ã¹ã¿ã€ããããã«ãŠã§ã¢ãã¡ã¯ããªãéåæããã«ãŠã§ã¢ããšã©ãŒåŠçããã«ãŠã§ã¢ããªã¯ãšã¹ãæ€èšŒããã«ãŠã§ã¢ãªã©ã®é«åºŠãªã¿ã€ããã¿ãŒã³ãç¿åŸããããšã§ãå ç¢ã§ã¹ã±ãŒã©ãã«ã§ã¿ã€ãã»ãŒããªExpressã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããŸããããã«ãŠã§ã¢é¢æ°ãå°ãããçŠç¹ãçµããååã«ããã¥ã¡ã³ãåããããã«ãã¹ããã©ã¯ãã£ã¹ã«åŸãããšãå¿ããªãã§ãã ããã