ããã«ã¡ã¯ïŒããã³ããšã³ããšã³ãžãã¢ã®åŒµã§ãïŒ ãã®èšäºã¯ Enigmo Advent Calendar 2025 ã®8æ¥ç®ã®èšäºã§ãã ãåå®å
šãããå
ç¢æ§ãããéçºäœéšããã©ãããšã³ãžãã¢ã§ããããè¿å¹ŽããèãããŒã¯ãŒãã ãšæããŸããç¹ã«ãŠã§ãéçºãããã³ããšã³ãéçºçéã§ã¯ãããããæ¹åããããã«TypeScriptãå°å
¥ã»æ¡çšããããŒã ãå¢ããäžæ¹ã§ãã ã§ãããããã§ã¯è¶³ããªãããã£ãšå
ç¢çããã€ä¿å®ããããTypeScriptãæžãããïŒãã ãšäž»åŒµããã³ãã¥ããã£ãå®ã¯ååšããŠããŠã圌ãããã©ãçãã解決çã¯ä»åç§ãå°å
¥ãæ€èšãã Effect TS ã§ãã ç§ã®èª¿æ»ã説æããåã«ãèšäºãããããããããããã«ããŸãã¯ããã€ãã®ããŒã¯ãŒããå®çŸ©ããããšæããŸãã ããŒã¯ãŒã åå®å
š ããã°ã©ãã³ã°èšèª ããããã¯äžéšã®èšèª(TypeScriptãªã©)ã«ãããŠã¯ã ã©ã€ãã©ãª ã圢容ããåèªãåå®å
šãªèšèªã»ã©ã€ãã©ãªã¯ ã³ã³ãã€ã« æãããã¯ã©ã³ã¿ã€ã ïŒå®è¡æïŒã«åã®èª€çšãæ€ç¥ã§ããŠãéçºè
ã«ãããå ±åããããããã°ã©ã ãäžæ¢ãããããããšãã§ããŸãã ã³ã³ãã€ã« æãã©ã³ã¿ã€ã äž¡æ¹ã§åã®èª€çšã培åºçã«é²ã Rust ã¯ä»£è¡šæ Œã®äžã€ã§ãã Rust ã»ã©ã§ã¯ãããŸããããä»åã®ããŒãã«ãªã TypeScript ãåå®å
šãªèšèªã ãšèªèãããŠããŸãã å
ç¢æ§ ããã°ã©ã ãæ³å®ãã圢åŒã§æ§ã
ãªã·ããªãªã察å¿ããèœåã§ããå
·äœçã«è©±ããŸããšãå¯èœãªãšã©ãŒãæ€ç¥ããŠãé©åãªåŠçãå®è¡ããããç¡å¹ãªã€ã³ãããã«å¯ŸããŠãæ£ããåŠçã§å¯ŸåŠãããããããšãå
ç¢æ§ã®é«ããœãããŠã§ã¢ã®ææšãšãªããŸãã éçºäœéš ç°¡åã«èšããŸããšãéçºã®å¿«é©ããšããæå³ã§ãããšãã£ã¿ãŒ( VS Code ãªã©)ãšLSP (Language Server Protocol) ã§å®çŸããããªãŒãã³ã³ããªãŒããšããéçºäœéšãæ¹åããŠãŸããã»ãã«ã¯ãLLM ã«ããã³ãŒãäºæž¬ãªã©ãéçºäœéšãåäžãããŠãããšæãããŠããŸãã å°å
¥ãæ€èšããçç± ããŒã¯ãŒããç°¡åã«èª¬æã§ããŸããã®ã§ãä»åå°å
¥ãæ€èšããçç±ã説æããããšæããŸãã å®ã¯æå±ããŠããããŒã ãæ¥å¹Žããã³ãŒãããŒã¹ãMeta瀟㮠Flow-Typed ãã TypeScript ã«ç§»è¡ããäºå®ãªã®ã§ãç§ã¯çæ³ç㪠TypeScript ã®æžãæ¹ã暡玢äžã§ãã ãã®äžãEffect TS ãšããæ°ã«ãªã£ãŠããã©ã€ãã©ãªãæãæµ®ããã§ã調æ»ãå§ããŸããã æ°ã«ãªã£ãŠãããšãããªãã§ããããŸãã«ãåå®å
šããšãå
ç¢æ§ãã®éšåã§ããã Effect Type ãã®ååã®éããEffect TSã®éªšå¹¹ãšãªãã®ã¯ã Effect ãšããããŒã¿ã¹ãã©ã¯ãã£ãŒã§ããEffect TSã«ãããŠãäžåã®åŠçã®èµ·ç¹ã Effect ã«ãªã£ãŠããŠããªã«ããå®è¡ããããããŸãã¯ãã®åŠçã説æãã Effect ãå®è£
ããªããšãããŸããã ãããŠããã® Effect ã§ãããåŸæ¥ã® JavaScript ã®ãªããžã§ã¯ããšã颿°ãšãéã£ãŠãåŠçã®çµæ(success type)ããšã©ãŒ(error type)ãšäŸåé¢ä¿(dependencies)ãå
å
ããŠããŸãããããããã説æããŸããšã Rust ã«ãã Result Type ã«äŒŒãŠããŸãã ãã® ã·ã°ãã㣠ã以äžã«ãªããŸã Effect< Success , Error , Requirements > Error Type äŸåé¢ä¿ã«ã€ããŠã¯è©±ãæŽã«è€éã«ããŸãã®ã§ãä»åã¯å²æãããŠããã ããŸããã ãšã©ãŒ ã¯ããã°ã©ã ã®ãåå®å
šããšãå
ç¢æ§ãã倧å¹
ã«æ¹åããããšãã§ããŸãã çç±ãšããŠã¯ãTypeScript ãå«ãããããã® ããã°ã©ãã³ã°èšèª ã¯ãšã©ãŒãåã®äžéšãšããŠèªèããŠããŸããã®ã§ãåã§å®å
šã«åŠçãæ£ããå®è¡ãããããšãä¿èšŒã§ããŸããã ãããã°ã以äžã¯ tsc (TypeScript Compiler) ããäœã®èŠåããªããã§ããã fallibleFn ã倱æããŠã console.log ãŸã§å®è¡ãããªãå¯èœæ§ããããŸããã Effect TS ã Rust ãªã©ãšã©ãŒãåãšããŠæ±ãã¿ã€ãã·ã¹ãã ã§ã¯ããããããšãæ®ã©çºçããŸããã const fn = () => { const result = fallibleFn(); console .log( `The result is: ${ result } ` ); } ; const fallibleFn = () => { if ( Math . random () > 0.5 ) { return "hello world" ; } else { throw new Error ( "oops" ); } } ; Effect TSã§ã®å®è£
ã§ã¯ã tsc ã®åè©äŸ¡ã§é¢æ°ã倱æããããšãããããšãããããŸã const fnEffect = Effect.gen( function* () { const result = yield* fallibleEffect; yield * Console . log ( `The result is ${ result } ` ); } ); const fallibleEffect = Effect.try(() => { if ( Math . random () > 0.5 ) { return "hello world" ; } else { throw new Error ( "oops" ); } } ); error typeã UnknownExceptionã«ãªã£ãŠããŸã å
ç¢æ§ã«é¢ããŠã§ãããäžè¿°ã®ããã«ããšã©ãŒãæã£ãŠãã Effect ãå®è¡ããããè¿ãå€ã«ãªã Effect ãå¿
ã ãšã©ãŒãæã€ããšã«ãªããŸãããããå®å
šã«ãªããããã«ã¯ãããåŠçããããšã¯å¿
èŠã§ãããããŠãåŠçããæãEffect TSã¯éçºè
ãå¯èœãªãšã©ãŒãå
šéšå¯ŸåŠããããšãèŠæ±ããŸãã 以äžã® ã¹ãããã 㯠interestingFallibleEffect ãšãããšã©ãŒãæã€ Effect ããšã©ãŒãªãã® Effect ã«ããåŠçã§ããå¯èœãªãšã©ãŒãå
šéšå¯Ÿå¿ããªããšãåãããšã©ãŒãæ¶ããŸããã class InterestingError extends Data.TaggedError( "InterestingError" )< { readonly message : string ; } > {} class MoreInterestingError extends Data.TaggedError( "MoreInterestingError" )< { readonly message : string ; } > {} const interestingFallibleEffect = Effect.gen( function* () { const random = Math . random (); if (random > 0.5 ) { return "hello world" ; } if (random > 0.25 ) { return yield* Effect.fail( new InterestingError( { message : "interesting error" } )); } return yield* Effect.fail( new MoreInterestingError( { message : "more interesting error" } )); } ); const errorFreeInterestingFallibleEffect = interestingFallibleEffect.pipe( Effect.catchTags( { InterestingError : () => Effect.succeed( "failed interestingly" ), MoreInterestingError : () => Effect.succeed( "failed even more interestingly" ), } ), ); ãšã©ãŒããªã(never)ã«ãªã£ãŠããŸã å®è£
ã®è©³çްãè²ã
端æã£ãŠèª¬æããŠããŸããŸããããEffect TSã Error Type ãéããŠãåå®å
šããšãå
ç¢æ§ããæ¹åã§ããããšãããçšåºŠäŒãããããšæããŸãã çµè«ãšããŠãç§ãã§ããã°ãœãããŠã§ã¢ãå
ç¢ã«äœãããæ¹ãªã®ã§ãä»åã®èª¿æ»ã決æããŸããã æ¢åã³ãŒããEffect TSã§å®è£
ããŠã¿ãŸãã ããã§ã¯æ¬é¡ã«å
¥ããŸãïŒãã®ãã³ãå®éã®æ¥åã«Effect TSãå°å
¥ããããæ€èšããããã«ã Buyma ã®ããã³ããšã³ãã®ã³ãŒãããé©åãªåŠçãéžãã§ãEffect TSã§å®è£
ããŠã¿ãŸããã Effect TSã®é·æã掻çšããããã«ã以äžã®åºæºã§åŠçãéžã³ãŸããã ãšã©ãŒãçºçããå¯èœæ§ããåŠç ãªãã©ã€ãå¿
èŠãªåŠç ãäºãã«äŸåæ§ãããåŠçããã§ããåŠç çµæçã«ãããããåŠçãEffect TSã§å®è£
ããŠã¿ãŸãã: ã¡ãã»ãŒãžããµãŒããŒã«éãåŠç: ã¡ãã»ãŒãžãéãåã«ããµãŒããŒã«ã¡ãã»ãŒãžã®å
容ãéã£ãŠãããªããŒã·ã§ã³ãå®è¡ããŠããããŸãã倱æã®å Žåã400ç³»ã®status codeãè¿ããŸããèªèšŒãšã©ãŒã®å Žåã ãã ããŒã¯ ã³æŽæ°ãå®è¡ããŠããªãã©ã€ããŸããæçµçã«å€±æããŠããŸããããå
šäœã®åŠçãäžæ¢ã«ãªããŸãã ã¡ãã»ãŒãžã®æ¬æãéããŸãã3åãŸã§ãªãã©ã€ãå¯èœã§ãèªèšŒãšã©ãŒã®å Žåããªãã©ã€ã®åã«ã ããŒã¯ ã³æŽæ°ãè¡ããŸãããæŽæ°ã倱æããå Žåããªãã©ã€ãäžæ¢ã«ãªããŸããæçµçã«å€±æããå Žåãå
šäœã®åŠçãäžæ¢ã«ãªããŸãã 2ã€ç®ã®æ¬æãéããŸãã3åãŸã§ãªãã©ã€ãå¯èœã§ãèªèšŒãšã©ãŒã®å Žåããªãã©ã€ã®åã«ã ããŒã¯ ã³æŽæ°ãè¡ããŸãããæŽæ°ã倱æããå Žåããªãã©ã€ãäžæ¢ã«ãªããŸããæçµçã«å€±æããå Žåãå
šäœã®åŠçãäžæ¢ã«ãªããŸãã Effect TS ã®æžãæ¹ãäœéšããããã®å®è£
ãªã®ã§ãå®è£
ã®å
容ã¯ç°¡ç¥åãããŠããŸããããã³ããšã³ãã®å®è£
ãå«ãŸããŠããŸããšãæŽã«åããã«ãããªããããä»åã¯HTTPãªã¯ãšã¹ãã®åŠçã ããå®è£
ããŸããã API ãåŒã¶ ãŸãã¯ãHTTPãªã¯ãšã¹ããåŠçããEffectãäœæããŸããã const callAPI = ( url : string ) => Effect.gen( function* () { const client = yield* makeAuthenticatedClient; const response = yield* client. get (url).pipe( Effect.catchAll(( error ) => { if (HttpClientError.isHttpClientError(error) && "response" in error) { const status = error. response . status ; return Console . log ( `API Error [ ${ status } ] at ${ url } ` ).pipe( Effect.andThen( Effect.fail( new APIError( { message : `HTTP ${ status } error at ${ url } ` , status , } ), ), ), ); } return Console . log ( `Network error at ${ url } ` ).pipe( Effect.andThen( Effect.fail( new APIError( { message : `Network error at ${ url } ` , status : 0 , } ), ), ), ); } ), ); const json = yield* response.json.pipe( Effect.catchAll(( _error ) => { return Console . log ( `JSON parse error at ${ url } ` ).pipe( Effect.andThen( Effect.fail( new APIError( { message : `Failed to parse JSON response at ${ url } ` , status : response. status , } ), ), ), ); } ), ); yield * Console . log ( `Response from ${ url } : ${ json } ` ); return json; } ); HTTP fetchã®ãªã¯ãšã¹ããçºç«ããŠããšã©ãŒã APIError ã«çµ±äžããŠãæåããå ŽåãçµæãåºåEffect ã§ãã makeAuthenticatedClient ãšãã Effect ããHTTP ClientãååŸããŠããŸãããäŸåé¢ä¿ã®è©±ã«ãªããŸãã®ã§ã詳现ã¯å²æãããŠããã ããŸããç°¡åã«èšããŸããšãEffect TS㯠äŸåæ§æ³šå
¥ ãæšå¥šããŠããŠãHTTP Clientãªã©ã®å
±é颿°ã¯äŸåæ§ãšããŠEffectã«æäŸããããšãå€ããä»åç§ãããå®è£
ããŠããŸãããããŠã fetch ã®ãšãã§ã¯ãåã®ã³ã¹ããçãããã«ã @effect/platform ããã±ãŒãžã® HttpClient ã䜿çšããŠãããŸãã ããŒã¯ ã³ãæŽæ°ãã 以äžã®å®è£
ã§HTTPãªã¯ãšã¹ããçºç«ããããšãã§ããããã«ãªããŸããã®ã§ã次㯠ããŒã¯ ã³ãæŽæ°ããåŠçãå®è£
ããŸããããããŸã§æžãæ¹ãæ€èšŒããããã®å®è£
ãªã®ã§ãç°¡ç¥åãããå®è£
ãšãªããŸãã const renewToken = Effect.gen( function* () { yield * Console . log ( "Renewing token..." ); const client = yield* HttpClient.HttpClient; const { token } = yield* AuthToken; const response = yield* client.post(RENEW_URL); const json = yield* response.json; const newToken = (json as { token : string ; } ).token; yield * Ref. set (token, newToken); yield * Console . log ( "token renewed" ); } ).pipe( Effect.catchAll(() => Effect.fail( new APIError( { message : "Token renewal failed" , status : 0 , } ), ) ), ); ãã¡ãã¯HttpClient以å€ã«ãAuthToken ãšãããµãŒãã¹ããEffectéã«å
±æãããŠãã ããŒã¯ ã³(token) ãžã®åç
§(Ref) ãååŸããŠããŠãããçµç±ã§å
±æã®å€æ°ãæŽæ°ããŠããŸãããã®å€æ°ã¯äžè¿°ã® makeAuthenticatedClient ã«ã䜿ãããŠããŸããããæŽæ°ãããããHTTP Clientã䜿ã ããŒã¯ ã³ãæŽæ°ããããã®ã«ãªããŸãã ãªãã©ã€ã ãªã«ããª ãŒæ©èœã远å åºæ¬ã®åŠçãæããŸããã®ã§ã次ã¯Effectããªãã©ã€ããEffectã«å€ããEffectãå®è£
ããŸãã const retryWithRecovery = < A , E , R , RA , RE , RR >( effect : Effect.Effect < A , E , R > , recoveryAction : Effect.Effect < RA , RE , RR > , recoveryPredicate : ( error : E ) => boolean , retryPredicate : ( error : E ) => boolean , maxRetries : number , ): Effect.Effect < A , E | RE , R | RR > => { const attempt = ( retriesLeft : number ): Effect.Effect < A , E | RE , R | RR > => effect.pipe( Effect.catchAll(( e ) => { if (retriesLeft > 0 && retryPredicate(e) && recoveryPredicate(e)) { return recoveryAction.pipe(Effect.andThen(attempt(retriesLeft - 1 ))); } if (retriesLeft > 0 && retryPredicate(e)) { return attempt(maxRetries - 1 ); } return Effect.fail(e); } ), ); return attempt(maxRetries); } ; ãžã§ããªã¯ã¹ ( generics ) ã®ããã§å°ãè€éã«èŠãããããããŸããããããèŠãŸããšçµæ§ç°¡åãªåŠçã§ãã åŒæ°ã説æããŸããšã effect: ã¡ã€ã³åŠçã® effect ãæåæã¯ A åã®å€ãè¿ããŠã倱ææã¯ E åã®å€ãè¿ããŸããäŸåé¢ä¿ã¯ R åã§ãã recoveryAction: 倱æããããæ¬¡ã®ã¡ã€ã³åŠçãå®è¡ããåã«å®è¡ããã effect ãæ¬¡ã®ã¡ã€ã³åŠçã倱æããªãããã«ããã°ã©ã ã®ã¹ããŒãããªã«ããŒããåŠçã§ããæåæã¯ RA åã®å€ãè¿ããŠã倱ææã¯ RE åã®å€ãè¿ããŸããäŸåé¢ä¿ã¯ RR åã§ãã recoveryPredicate: ãªã«ã㪠ãŒãå®è¡ãããã倿ãã颿°ã true ãè¿ããããã ãªã«ã㪠ãŒãå®è¡ãããŸãã retryPredicate: ãªãã©ã€ãå®è¡ãããã倿ãã颿°ã true ãè¿ããããããªãã©ã€ãå®è¡ãããŸãã maxRetries: æå€§ãªãã©ã€æ°ã0ã«ãªã£ããã recoveryPredicate ã retryPredicate ã®çµæé¢ä¿ãªãã§ããªãã©ã€ãå®äºããŸãã åŒæ°ã®æå³ãããããŸããããåŠçãããããããªãããšæããŸããã€ãŸãããã®åŠçã¯ãã¡ã€ã³åŠçã«ãªãã©ã€ããæ©èœã远å ããŠããŸãããã®äžã«ããªãã©ã€ã®åºæºã ããŒã¯ ã³æŽæ°ãªã©ã® ãªã«ã㪠ãŒåŠçã ãªã«ã㪠ãŒåŠçãå®è¡ããåºæºãæå®ãããããšã§ããã£ãšæè»ãªãªãã©ã€åŠçãäœæããããšãå¯èœã«ããŠããŸããåçŽã« Effect ããªãã©ã€ãããã§ããã°ã Effect.retry ãšãããã«ããŒã䜿ã£ããããã§ãããä»ååèã«ãªã£ãæ¢åå®è£
ã¯å®é ãªã«ã㪠ãŒãèæ
®ããå®è£
ãªã®ã§ããã®ããã«å®è£
ããŸããã 以äžã®åŠçã¯æ±ºããŠè€éãªåŠçã§ã¯ãªããŠãEffect TSãªãã§ãå®è£
ã§ãããšæããããããŸããããEffect TSã®ãããã§ããã® Effect ããçæããã Effect ã¯æçµçã«çºçããå¯èœæ§ããããšã©ãŒãšãå¿
èŠãªäŸåé¢ä¿ãå
šéšåæ
å ±ãšããŠä¿åããŠããŸãããã®åãã¯æçµã®ä»äžããèŠããããåããã«ãªãããšæããŸãã ä»äžã 以äžå®è£
ãããã®ãçµã¿åãããŠãä»äžãããã®ã以äžãšãªããŸãã // ããªããŒã·ã§ã³ const callAPI1 = retryWithRecovery( callAPI(API_1), renewToken, ( e ) => e. status === 401 , ( e ) => e. status === 401 , 3 , ); // æ¬æ1 const callAPI2 = retryWithRecovery( callAPI(API_2), renewToken, ( e ) => e. status === 401 , () => true , 3 , ); // æ¬æ2 const callAPI3 = retryWithRecovery( callAPI(API_3), renewToken, ( e ) => e. status === 401 , () => true , 3 , ); // é çªã§åŠçãåŒã¶ const callAPIs = callAPI1.pipe(Effect.andThen(callAPI2), Effect.andThen(callAPI3)); // äŸåæ§æ³šå
¥ const mergedLayer = Layer.merge(FetchHttpClient.layer, AuthTokenLive); const program = callAPIs.pipe( Effect.provide(mergedLayer), Effect.catchAll(( error ) => Console . log ( `Main operation failed: ${ error.message } ` )), ); Effect.runPromise(program); åæºåã¯ãŸããŸãè€éã§ãããã颿°åã®ã©ã€ãã©ãªã®ãããåºæ¬ã®éšåãæºåã§ããããæçµã®çµã¿åããã¯çµæ§æ¥œã§ãã颿°åã«ãŸã æ
£ããŠããªãæ¹ã«ãèªã¿ã«ããéšåãããããšæããŸãããããçšåºŠè§ŠããŠãŸããããèªã¿ãããæããããšæããŸãã(ç§ã颿°åŒåå¿è
ã§ããããããæ
£ããŠããŠããŸã) ããšãåè¿°ããéããæåŸã«å®è¡ãããã»ãã® effect ã®åæ
å ±ããèŠãããããšæããŸãã ãšã©ãŒåŠçãäŸåæ§æ³šå
¥åã®effect (æçµeffectçŽå) åã«èª¬æããéãã«ã3ã€ã®åŠçã§çºçããå¯èœæ§ããããšã©ãŒãšå¿
èŠãªäŸåé¢ä¿ã瀺ããŠããŸãã(ä»åã¯APIErrorããäœæããŠãªããŠãããäžã€ã«ãªã£ãŠãŸãã) æçµçã«å®è¡ãããeffect ãšã©ãŒãåŠçããããšã§ã Error Type ã ãªã( never ) ã«å€ããŠãäŸåæ§ãæäŸããããšã§ã Dependencies ã ãªã( never ) ã«ããŠããŸã 以äžã§ãç°¡ç¥åãšã¯ãããæ¥åäžã«å®éã«ããã¡ãã£ãšè€éãªåŠçãEffect TSã§å®è£
ããŠã¿ãŸãããæã£ãããé·ããªããŸãããããããŸã§ã芧ã«ãªã£ãŠãã ãã£ãŠãããããšãããããŸãïŒ æ€èšçµæ å®è£
ã®èª¬æãé·ããªããŸããããå°å
¥ã®æ€èšã§ããã®ã§ãæ€èšã®çµæãã¡ãããšèª¬æããŠãããããšæããŸãã ã¡ãªãã åã®å®å
šæ§ãéåžžã«é«ãããšã©ãŒãåæ
å ±ã«å
¥ã£ãŠããŸãã®ã§ãåžžã«æ±ã£ãŠãã倿°ã®åãããããŸããTypeScript ããã®æ
å ±ã§ããç確ãªã¿ã€ããã§ãã¯ãã§ããŸãã éçºè
ã®æžãæ¹ã«ããããŸãããå
ç¢æ§ãéåžžã«é«ããŠãéçºæ®µéã§å¯èœãªã·ããªãªãã ãããåæ
å ±ããèªç¥ã§ããŸãã å¶åŸ¡ãããŒã®å¯èŠåãåŸæ¥ã® catch ã throw ãã¿ãŒã³ã§ã¯ãªãããšã©ãŒãå€ãšããŠæ±ãããšã§ãåŠçããããé¢ããŠãã catch block ã«é£ã°ãããããšãé²ããŠããŸããå人å人ã®å¥œã¿ã«ããããŸãããç§ã¯ãã¡ãã®ã»ããããããããšæããŸãã ãã¡ãªãã ç¿åŸããã®ããããé£ããã§ãã颿°åŒã®ç¹æ§ãéåžžã«åŒ·ããŠãããçšåºŠé¢æ°åŒã®çµéšããªããšçè§£ãã«ããããšæããŸãããã®äžã«ãäŸåæ§æ³šå
¥ãçµæ§çµã¿èŸŒãŸããŠããŸããããããã«é¢ããŠããäžå®ã®ç¥èãå¿
èŠãšãªããŸãããã©ã°ã©ãã³ã°åå¿è
ã«ã¯åããŠããªãããšæããŸãã ã¢ããªå
šäœãEffect TSã§å®è£
ãããŠããªããšããŸãæå³ããããŸãããåœç¶ã®ããšãªãã§ãããEffect TSãåã®å®å
šãä¿èšŒããŠããã®ã¯ Effect ã®äžã ããªã®ã§ãEffect TS以å€ã®åŠçãæ··ãã£ãŠããŸããšãåå®å
šãå®å
šã§ã¯ãªããªããŸãã ã³ãŒããå
ç¢çã«æžããã ãã¬ãŒã ã¯ãŒã¯ ãªã®ã§ãã³ãŒãã®å
ç¢æ§ã¯é«ãŸããŸãããéçºã®ã³ã¹ããæ¯èŒçã«é«ãããšæããŸãã çµè« çµè«ãããããŸããšãä»ã®ãšãããEffect TSã®å°å
¥ã¯ããªãããšæããŸããå人çã«ã¯Effect TSã®ã¡ã³ã¿ã«ã¢ãã«ãåã®å®å
šæ§ãªã©ãéåžžã«å¥œãã§ããŸãããäžè¿°ã®éãã«ãããŒã ã«å°å
¥ããã«ã¯ã³ã¹ãã倧ããããŸããããé£ããããšæããŸããããŒã ã¡ã³ããŒãå
šå¡èå³ãæã£ãŠããŠãç¿åŸããŠãããããšã«ãªã£ãŠããŠãæ¢åã®ã¢ããªã«ããã远å ããã®ã¯ã³ã¹ããé«ããŠãã¡ãªãããå°ãªãã§ãããªã®ã§ãæ°èŠã®ã³ãŒãããŒã¹ããã£ãŠãããŒã ã¡ã³ããŒãã¿ããªEffect TSã§éçºããããšæããªãéããEffect TSã®å°å
¥ã¯é£ããããšæããŸãã ãšã¯ãããç§ã¯ãã®èª¿æ»ãéããŠãEffect TSã«æŽã«èå³ãæã€ããã«ãªããŸããã®ã§ãå人éçºãå°èŠæš¡ã®éçºãªã©ã«äœ¿ã£ãŠãããããšèããŠãããŸããçããããã®èšäºãèªãã§ãèå³ãæã€ããã«ãªã£ããããã²Effect TSã䜿ã£ãŠã¿ãŠãã ããïŒ ãããã« 10æ¥ã®èšäºã®æ
åœã¯ ãšã³ãžã㢠ã®å°æŸããã§ãããæ¥œãã¿ã«ã ããŸã ãã®èšäºã«èšèŒãããŠããã³ãŒãã¯ç§ã® GitHub ã«ãäžããŠããŸãã®ã§ãèå³ãããæ¹ã¯ãã²ã芧ã«ãªã£ãŠãã ããïŒ Effect Sample Codeã¯ãã¡ã