TypeScriptãããµãŒãã¹éã®éä¿¡ã«ãããåå®å šæ§ã確ä¿ããããšã§ãã€ã¯ããµãŒãã¹ã¢ãŒããã¯ãã£ãã©ã®ããã«åŒ·åããããæ¢ããŸãããã¹ããã©ã¯ãã£ã¹ãšå®è£ æŠç¥ãåŠã³ãŸãããã
TypeScriptãã€ã¯ããµãŒãã¹ïŒãµãŒãã¹éã®éä¿¡ã«ãããåå®å šæ§ã®å®çŸ
ãã€ã¯ããµãŒãã¹ã¢ãŒããã¯ãã£ã¯ãã¹ã±ãŒã©ããªãã£ã®åäžãç¬ç«ãããããã€ãæè¡ç倿§æ§ãªã©ãå€ãã®å©ç¹ãæäŸããŸããããããè€æ°ã®ç¬ç«ãããµãŒãã¹ã®é£æºã¯è€éããå¢ããç¹ã«ããŒã¿ã®æŽåæ§ãšä¿¡é Œæ§ã®é«ãéä¿¡ã確ä¿ããéã«èª²é¡ãçããŸããTypeScriptã¯ããã®åŒ·åãªåã·ã¹ãã ã«ããããããã®èª²é¡ã«å¯ŸåŠãããã€ã¯ããµãŒãã¹éã®çžäºäœçšã®å ç¢æ§ãé«ããããã®åŒ·åãªããŒã«ãæäŸããŸãã
ãã€ã¯ããµãŒãã¹ã«ãããåå®å šæ§ã®éèŠæ§
ã¢ããªã·ãã¯ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãããŒã¿åã¯éåžžãåäžã®ã³ãŒãããŒã¹å ã§å®çŸ©ãããé©çšãããŸããäžæ¹ããã€ã¯ããµãŒãã¹ã¯ãå€ãã®å Žåãç°ãªãããŒã ãæè¡ãããã³ãããã€ç°å¢ã䌎ããŸããããŒã¿æ€èšŒã®ããã®äžè²«æ§ããããä¿¡é Œæ§ã®é«ãã¡ã«ããºã ããªããã°ãçµ±åãšã©ãŒãã©ã³ã¿ã€ã ãšã©ãŒã®ãªã¹ã¯ãå€§å¹ ã«å¢å ããŸããåå®å šæ§ã¯ãã³ã³ãã€ã«æã«å³å¯ãªåãã§ãã¯ãé©çšãããµãŒãã¹éã§äº€æãããããŒã¿ãäºåã«å®çŸ©ãããå¥çŽã«æºæ ããŠããããšã確èªããããšã«ããããããã®ãªã¹ã¯ã軜æžããŸãã
åå®å šæ§ã®å©ç¹ïŒ
- ãšã©ãŒã®åæžïŒåãã§ãã¯ã¯ãéçºã©ã€ããµã€ã¯ã«ã®æ©ã段éã§æœåšçãªãšã©ãŒãç¹å®ããã©ã³ã¿ã€ã ã§ã®é©ããã³ã¹ãã®ããããããã°äœæ¥ãé²ããŸãã
- ã³ãŒãå質ã®åäžïŒåã¢ãããŒã·ã§ã³ã¯ãã³ãŒãã®å¯èªæ§ãšä¿å®æ§ãåäžãããéçºè ããµãŒãã¹ã€ã³ã¿ãŒãã§ãŒã¹ãçè§£ãã倿ŽããããããŸãã
- ã³ã©ãã¬ãŒã·ã§ã³ã®åŒ·åïŒæç¢ºãªåå®çŸ©ã¯ããµãŒãã¹éã®å¥çŽãšããŠæ©èœããç°ãªãããŒã éã®ã·ãŒã ã¬ã¹ãªã³ã©ãã¬ãŒã·ã§ã³ãä¿é²ããŸãã
- ä¿¡é Œæ§ã®åäžïŒåå®å šæ§ã¯ããã€ã¯ããµãŒãã¹éã®çžäºäœçšã®æ£ç¢ºæ§ãšä¿¡é Œæ§ã«å¯Ÿããèªä¿¡ãé«ããŸãã
TypeScriptã«ãããåå®å šãªãµãŒãã¹éä¿¡ã®ããã®æŠç¥
TypeScriptããŒã¹ã®ãã€ã¯ããµãŒãã¹ã§åå®å šãªãµãŒãã¹éä¿¡ãå®çŸããããã«ãããã€ãã®æ¹æ³ãæ¡çšã§ããŸããæé©ãªæŠç¥ã¯ãç¹å®ã®éä¿¡ãããã³ã«ãšã¢ãŒããã¯ãã£ã«ãã£ãŠç°ãªããŸãã
1. å ±æåå®çŸ©
1ã€ã®ç°¡åãªæ¹æ³ã¯ãå ±æåå®çŸ©ãäžå€®ãªããžããªïŒããšãã°ãå°çšã®npmããã±ãŒãžãŸãã¯å ±æGitãªããžããªïŒã§å®çŸ©ããåãã€ã¯ããµãŒãã¹ã«ã€ã³ããŒãããããšã§ããããã«ããããã¹ãŠã®ãµãŒãã¹ã亀æãããããŒã¿æ§é ã«ã€ããŠäžè²«ããçè§£ãæã€ããã«ãªããŸãã
äŸïŒ
Order ServiceãšPayment Serviceã®2ã€ã®ãã€ã¯ããµãŒãã¹ãæ€èšããŠãã ããããããã¯ã泚æã𿝿ãã«é¢ããæ å ±ã亀æããå¿ èŠããããŸããå ±æåå®çŸ©ããã±ãŒãžã«ã¯ã次ã®ãããªãã®ãå«ãŸããŸãã
// shared-types/src/index.ts
export interface Order {
orderId: string;
customerId: string;
items: { productId: string; quantity: number; }[];
totalAmount: number;
status: 'pending' | 'processing' | 'completed' | 'cancelled';
}
export interface Payment {
paymentId: string;
orderId: string;
amount: number;
paymentMethod: 'credit_card' | 'paypal' | 'bank_transfer';
status: 'pending' | 'completed' | 'failed';
}
Order ServiceãšPayment Serviceã¯ããããã®ã€ã³ã¿ãŒãã§ãŒã¹ãã€ã³ããŒããããããã䜿çšããŠAPIå¥çŽãå®çŸ©ã§ããŸãã
// order-service/src/index.ts
import { Order } from 'shared-types';
async function createOrder(orderData: Order): Promise<Order> {
// ...
return orderData;
}
// payment-service/src/index.ts
import { Payment } from 'shared-types';
async function processPayment(paymentData: Payment): Promise<Payment> {
// ...
return paymentData;
}
å©ç¹ïŒ
- å®è£ ãšçè§£ãç°¡åã§ãã
- ãµãŒãã¹å šäœã§äžè²«æ§ã確ä¿ããŸãã
æ¬ ç¹ïŒ
- ãµãŒãã¹éã®å¯çµå â å ±æåã®å€æŽã«ã¯ããã¹ãŠã®äŸåãµãŒãã¹ã®åãããã€ãå¿ èŠã§ãã
- ãµãŒãã¹ãåæã«æŽæ°ãããªãå ŽåãããŒãžã§ãã³ã°ã®ç«¶åãçºçããå¯èœæ§ããããŸãã
2. APIå®çŸ©èšèªïŒäŸïŒOpenAPI/SwaggerïŒ
OpenAPIïŒæ§SwaggerïŒãªã©ã®APIå®çŸ©èšèªã¯ãRESTful APIãèšè¿°ããããã®æšæºåãããæ¹æ³ãæäŸããŸããTypeScriptã³ãŒãã¯ãOpenAPI仿§ããçæã§ãããããåå®å šæ§ã確ä¿ãããå®åã³ãŒããåæžãããŸãã
äŸïŒ
Order Serviceã®OpenAPI仿§ã¯ã次ã®ããã«ãªããŸãã
openapi: 3.0.0
info:
title: Order Service API
version: 1.0.0
paths:
/orders:
post:
summary: Create a new order
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
responses:
'201':
description: Order created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
components:
schemas:
Order:
type: object
properties:
orderId:
type: string
customerId:
type: string
items:
type: array
items:
type: object
properties:
productId:
type: string
quantity:
type: integer
totalAmount:
type: number
status:
type: string
enum: [pending, processing, completed, cancelled]
openapi-typescriptã®ãããªããŒã«ã䜿çšããŠããã®ä»æ§ããTypeScriptåãçæã§ããŸãã
npx openapi-typescript order-service.yaml > order-service.d.ts
ããã«ãããOrder APIã®TypeScriptåãå«ãorder-service.d.tsãã¡ã€ã«ãçæãããä»ã®ãµãŒãã¹ã§äœ¿çšããŠåå®å
šãªéä¿¡ã確ä¿ã§ããŸãã
å©ç¹ïŒ
- æšæºåãããAPIããã¥ã¡ã³ããšã³ãŒãçæã
- ãµãŒãã¹ã®çºèŠå¯èœæ§ã®åäžã
- å®åã³ãŒãã®åæžã
æ¬ ç¹ïŒ
- OpenAPI仿§ã®åŠç¿ãšä¿å®ãå¿ èŠã§ãã
- åçŽãªå ±æåå®çŸ©ãããè€éã«ãªãå¯èœæ§ããããŸãã
3. Protocol Buffersã䜿çšããgRPC
gRPCã¯ãProtocol Buffersãã€ã³ã¿ãŒãã§ãŒã¹å®çŸ©èšèªãšããŠäœ¿çšãã髿§èœãªãªãŒãã³ãœãŒã¹RPCãã¬ãŒã ã¯ãŒã¯ã§ããProtocol Buffersã䜿çšãããšããã©ãããã©ãŒã ã«äŸåããªãæ¹æ³ã§ããŒã¿æ§é ãšãµãŒãã¹ã€ã³ã¿ãŒãã§ãŒã¹ãå®çŸ©ã§ããŸããts-protoã@protobuf-ts/pluginãªã©ã®ããŒã«ã䜿çšããŠãProtocol Bufferå®çŸ©ããTypeScriptã³ãŒããçæã§ãããããåå®å
šæ§ãšå¹ççãªéä¿¡ãä¿èšŒãããŸãã
äŸïŒ
Order Serviceã®Protocol Bufferå®çŸ©ã¯ã次ã®ããã«ãªããŸãã
// order.proto
syntax = "proto3";
package order;
message Order {
string order_id = 1;
string customer_id = 2;
repeated OrderItem items = 3;
double total_amount = 4;
OrderStatus status = 5;
}
message OrderItem {
string product_id = 1;
int32 quantity = 2;
}
enum OrderStatus {
PENDING = 0;
PROCESSING = 1;
COMPLETED = 2;
CANCELLED = 3;
}
service OrderService {
rpc CreateOrder (CreateOrderRequest) returns (Order) {}
}
message CreateOrderRequest {
Order order = 1;
}
ts-protoããŒã«ã䜿çšããŠããã®å®çŸ©ããTypeScriptã³ãŒããçæã§ããŸãã
tsx ts-proto --filename=order.proto --output=src/order.ts
ããã«ãããOrder APIã®TypeScriptåãšãµãŒãã¹ã¿ããå«ãsrc/order.tsãã¡ã€ã«ãçæãããä»ã®ãµãŒãã¹ã§äœ¿çšããŠåå®å
šã§å¹ççãªgRPCéä¿¡ã確ä¿ã§ããŸãã
å©ç¹ïŒ
- 髿§èœã§å¹ççãªéä¿¡ã
- Protocol Buffersã«ãã匷åãªåå®å šæ§ã
- èšèªã«äŸåããªã â è€æ°ã®èšèªããµããŒãã
æ¬ ç¹ïŒ
- Protocol BuffersãšgRPCã®æŠå¿µãåŠã¶å¿ èŠããããŸãã
- RESTful APIãããèšå®ãè€éã«ãªãå¯èœæ§ããããŸãã
4. åå®çŸ©ã䜿çšããã¡ãã»ãŒãžãã¥ãŒãšã€ãã³ãé§ååã¢ãŒããã¯ãã£
ã€ãã³ãé§ååã¢ãŒããã¯ãã£ã§ã¯ããã€ã¯ããµãŒãã¹ã¯ã¡ãã»ãŒãžãã¥ãŒïŒäŸïŒRabbitMQãKafkaïŒãä»ããŠéåæçã«éä¿¡ããŸããåå®å
šæ§ã確ä¿ããããã«ã亀æãããã¡ãã»ãŒãžã®TypeScriptã€ã³ã¿ãŒãã§ãŒã¹ãå®çŸ©ããã¹ããŒãæ€èšŒã©ã€ãã©ãªïŒäŸïŒjoiãŸãã¯ajvïŒã䜿çšããŠãã©ã³ã¿ã€ã ã§ã¡ãã»ãŒãžãæ€èšŒããŸãã
äŸïŒ
補åã®åšåº«ã¬ãã«ã倿Žããããšãã«ã€ãã³ããçºè¡ããInventory Serviceãæ€èšããŠãã ãããã€ãã³ãã¡ãã»ãŒãžã¯ã次ã®ããã«å®çŸ©ã§ããŸãã
// inventory-event.ts
export interface InventoryEvent {
productId: string;
newStockLevel: number;
timestamp: Date;
}
export const inventoryEventSchema = Joi.object({
productId: Joi.string().required(),
newStockLevel: Joi.number().integer().required(),
timestamp: Joi.date().required(),
});
Inventory Serviceã¯ããã®ã€ã³ã¿ãŒãã§ãŒã¹ã«æºæ ããã¡ãã»ãŒãžãçºè¡ããä»ã®ãµãŒãã¹ïŒäŸïŒNotification ServiceïŒã¯ãããã®ã€ãã³ãããµãã¹ã¯ã©ã€ãããåå®å šãªæ¹æ³ã§åŠçã§ããŸãã
// notification-service.ts
import { InventoryEvent, inventoryEventSchema } from './inventory-event';
import Joi from 'joi';
async function handleInventoryEvent(message: any) {
const { value, error } = inventoryEventSchema.validate(message);
if (error) {
console.error('Invalid inventory event:', error);
return;
}
const event: InventoryEvent = value;
// Process the event...
console.log(`Product ${event.productId} stock level changed to ${event.newStockLevel}`);
}
å©ç¹ïŒ
- ãµãŒãã¹ã®åé¢ãšã¹ã±ãŒã©ããªãã£ã®åäžã
- éåæéä¿¡ã
- ã¹ããŒãæ€èšŒã«ããåå®å šæ§ã
æ¬ ç¹ïŒ
- åæéä¿¡ãšæ¯èŒããŠè€éããå¢ããŸãã
- ã¡ãã»ãŒãžãã¥ãŒãšã€ãã³ãã¹ããŒããæ éã«ç®¡çããå¿ èŠããããŸãã
åå®å šæ§ãç¶æããããã®ãã¹ããã©ã¯ãã£ã¹
ãã€ã¯ããµãŒãã¹ã¢ãŒããã¯ãã£ã§åå®å šæ§ãç¶æããã«ã¯ãèŠåŸãšãã¹ããã©ã¯ãã£ã¹ãžã®æºæ ãå¿ èŠã§ãã
- éäžååå®çŸ©ïŒãã¹ãŠã®ãµãŒãã¹ãã¢ã¯ã»ã¹ã§ããäžå€®ãªããžããªã«å ±æåå®çŸ©ãä¿åããŸãã
- ããŒãžã§ã³ç®¡çïŒå€æŽãšäŸåé¢ä¿ã管çããããã«ãå ±æåå®çŸ©ã«ã»ãã³ãã£ãã¯ããŒãžã§ãã³ã°ã䜿çšããŸãã
- ã³ãŒãçæïŒAPIå®çŸ©ãŸãã¯Protocol BuffersããTypeScriptåãèªåçã«çæããããã«ãã³ãŒãçæããŒã«ã掻çšããŸãã
- ã¹ããŒãæ€èšŒïŒããŒã¿ã®æŽåæ§ã確ä¿ããããã«ãç¹ã«ã€ãã³ãé§ååã¢ãŒããã¯ãã£ã§ã©ã³ã¿ã€ã ã¹ããŒãæ€èšŒãå®è£ ããŸãã
- ç¶ç¶çã€ã³ãã°ã¬ãŒã·ã§ã³ïŒãšã©ãŒãæ©æã«æ€åºããããã«ãåãã§ãã¯ãšãªã³ãã£ã³ã°ãCI/CDãã€ãã©ã€ã³ã«çµ±åããŸãã
- ããã¥ã¡ã³ãïŒAPIå¥çŽãšããŒã¿æ§é ãæç¢ºã«ææžåããŸãã
- ç£èŠãšã¢ã©ãŒãïŒåãšã©ãŒãšäžæŽåã«ã€ããŠãµãŒãã¹éä¿¡ãç£èŠããŸãã
é«åºŠãªèæ ®äºé
APIã²ãŒããŠã§ã€ïŒAPIã²ãŒããŠã§ã€ã¯ãåå¥çŽãé©çšããããã¯ãšã³ããµãŒãã¹ã«å°éããåã«ãªã¯ãšã¹ããæ€èšŒããäžã§éèŠãªåœ¹å²ãæããããšãã§ããŸãããŸããç°ãªã圢åŒéã§ããŒã¿ã倿ããããã«ã䜿çšã§ããŸãã
GraphQLïŒGraphQLã¯ãè€æ°ã®ãã€ã¯ããµãŒãã¹ããããŒã¿ãã¯ãšãªããããã®æè»ã§å¹ççãªæ¹æ³ãæäŸããŸããGraphQLã¹ããŒãã¯TypeScriptã§å®çŸ©ã§ãããããåå®å šæ§ã確ä¿ããã匷åãªããŒã«ã䜿çšå¯èœã«ãªããŸãã
å¥çŽãã¹ãïŒå¥çŽãã¹ãã¯ããµãŒãã¹ãã³ã³ã·ã¥ãŒããŒã«ãã£ãŠå®çŸ©ãããå¥çŽã«æºæ ããŠããããšãæ€èšŒããããšã«çŠç¹ãåœãŠãŠããŸããããã«ãããç Žå£ç倿Žãé²ãããµãŒãã¹éã®äºææ§ã確ä¿ã§ããŸãã
ããªã°ãããã¢ãŒããã¯ãã£ïŒããŸããŸãªèšèªã䜿çšããå Žåãå¥çŽãšããŒã¿ã¹ããŒãã®å®çŸ©ãããã«éèŠã«ãªããŸããJSON SchemaãProtocol Buffersãªã©ã®æšæºåœ¢åŒã¯ãããŸããŸãªæè¡éã®ã®ã£ãããåããã®ã«åœ¹ç«ã¡ãŸãã
çµè«
åå®å šæ§ã¯ãå ç¢ã§ä¿¡é Œæ§ã®é«ããã€ã¯ããµãŒãã¹ã¢ãŒããã¯ãã£ãæ§ç¯ããããã«äžå¯æ¬ ã§ããTypeScriptã¯ãåãã§ãã¯ãé©çšãããµãŒãã¹å¢çå šäœã§ããŒã¿ã®æŽåæ§ã確ä¿ããããã®åŒ·åãªããŒã«ãšãã¯ããã¯ãæäŸããŸãããã®èšäºã§æŠèª¬ãããŠããæŠç¥ãšãã¹ããã©ã¯ãã£ã¹ãæ¡çšããããšã«ãããçµ±åãšã©ãŒãå€§å¹ ã«åæžããã³ãŒãå質ãåäžããããã€ã¯ããµãŒãã¹ãšã³ã·ã¹ãã ã®å šäœçãªå埩åãé«ããããšãã§ããŸãã
å ±æåå®çŸ©ãAPIå®çŸ©èšèªãProtocol Buffersã䜿çšããgRPCããŸãã¯ã¹ããŒãæ€èšŒã䜿çšããã¡ãã»ãŒãžãã¥ãŒã®ããããéžæããŠããé©åã«å®çŸ©ãããé©çšãããåã·ã¹ãã ããæåãããã€ã¯ããµãŒãã¹ã¢ãŒããã¯ãã£ã®èŠç³ã§ããããšãå¿ããªãã§ãã ãããåå®å šæ§ãæ¡çšããã°ããã€ã¯ããµãŒãã¹ã¯ããªãã«æè¬ããã§ãããã
ãã®èšäºã§ã¯ãTypeScriptãã€ã¯ããµãŒãã¹ã®åå®å šæ§ã«ã€ããŠå æ¬çãªæŠèŠã説æããŸããããã¯ããœãããŠã§ã¢ã¢ãŒããã¯ããéçºè ãããã³å ç¢ã§ã¹ã±ãŒã©ãã«ãªåæ£ã·ã¹ãã ãæ§ç¯ããããšã«é¢å¿ã®ãããã¹ãŠã®äººã察象ãšããŠããŸãã