ããã«ã¡ã¯ãæ°åãšã³ãžãã¢ã® id:d-kimuson ã§ã å
æ¥ type-predicates-generator ãšããåå®çŸ©ãããŠãŒã¶ãŒå®çŸ©åã¬ãŒãã»ã¢ãµãŒã·ã§ã³é¢æ°ãèªåçæããããŒã«ããªãªãŒã¹ã㊠玹ä»èšäº ãæžããã®ã§ãããææ³ãšããçºããŠãããåããå€éšããæ¥ãå€ã«å®å
šãªåä»ããããããã®ã©ã€ãã©ãªãããŒã«ã®æ
å ±ãããã€ã芳枬ããŸãã ãã®èŸºãã®ã©ã³ã¿ã€ã ãã§ãã¯ã©ã€ãã©ãªã®æ
å ±ã£ãŠããŸããŸãšãŸã£ãŠããªãå°è±¡ã§èªåãç¥ããªããã®ãããã€ããã£ãã®ã§ã調ã¹ã€ã€ç°¡åã«ãŸãšããããããªãšæã£ãŠãã®ãšã³ããªãæžããŸãã å€éšãããã£ãŠããå€ãåå®å
šã«ããã«ã¯ãã£ãããš åçæã«ããã¢ãããŒã ã©ã³ã¿ã€ã ãã§ãã¯çšã®ç¬èªåãæžãããã¢ãããŒã åæ
å ±ããã©ã³ã¿ã€ã ãã§ãã¯é¢æ°ãèªåçæããã¢ãããŒã ã® 3 ã€ã®ã¢ãããŒãããããšæãã®ã§ãããããã®ã¢ãããŒãããšã«ç޹ä»ããŸã â åå®çŸ©ã®çæã«ããã¢ãããŒã å€éšããå€ããã£ãŠããäž»ããã±ãŒã¹ã¯ API éä¿¡ã§ãGraphQL ã OpenAPI ã®ã¹ããŒãããåå®çŸ©ãèªåçæããããšã§åå®å
šæ§ãå®ãã¢ãããŒãã§ã ã¹ããŒããšçæããŒã«ã®å®è£
ãæ£ãããšããåæã®å
ã§ãããå€éšãããã£ãŠããå€ã«æ£ãããäžå®æ
ä¿ããäžã§åãã€ããããšãã§ããŸã GraphQL Code Generator GitHub - dotansimha/graphql-code-generator: A tool for generating code based on a GraphQL schema and GraphQL operations (query/mutation/subscription), with flexible support for custom plugins. GraphQL ã®ã¹ããŒãããåå®çŸ©ãèªåçæããããŒã«ã§ã èªå㯠Gatsby ã§åäººã®æè¡ããã°ãæžããŠããŠãããã§äœ¿çšããŠãŸã å
¬åŒãµã€ã ã«äŸãèŒã£ãŠããã®ã§ãèŠãŠã¿ããšã€ã¡ãŒãžãããããšæããŸã openapi-generator GitHub - OpenAPITools/openapi-generator: OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3) OpenAPI ã¹ããŒãããåå®å
šã« API ãåŒã¹ã API ã¯ã©ã€ã¢ã³ããèªåçæããŠãããããŒã«ã§ã // openapi-generator + axios ã®ãµã³ãã«ã³ãŒã import axios from "axios" import { PetApiFactory , Configuration , PetStatusEnum } from "./typescript-axios" // èªåçæãããã³ãŒã const api = axios.create ( { /* config here */ } ) const config = new Configuration ( { /* config here */ } ) export const endpoints = PetApiFactory ( config , `baseURL` , api ) // APIã³ãŒã« endpoints .getPetById ( 0 /* åŒæ°ã«åãä»ã */ ) .then (( response ) => { response.data /* Pet ã«åãä»ã */ } ) aspida + openapi2aspida GitHub - aspida/aspida: TypeScript friendly HTTP client wrapper for the browser and node.js. aspida ãšããåå®å
šã« API ã³ãŒã«ãè¡ãããã®ã©ã€ãã©ãªãããã openapi2aspida ã䜿ãããšã§ã¹ããŒããã aspida ã®ã¯ã©ã€ã¢ã³ããèªåçæããŠãããŸã // aspida ã®ãµã³ãã«ã³ãŒã import axios from "axios" import aspida from "@aspida/axios" import api from "./api/$api" // èªåçæãããã³ãŒã const client = api ( aspida ( axios )) // API ã³ãŒã« client.pet ._petId ( 0 /* åŒæ°ã«åãä»ã */ ) . get() .then (( response ) => { response.body /* Pet ã«åãä»ã */ } ) openapi-generator 㯠TS ã«éããæ§ã
ãªèšèªã®ã¯ã©ã€ã¢ã³ããçæããŸãããopenapi2aspida 㯠TypeScript å°çšã§ãã䜿ããããå°è±¡ã§ã èªå㯠API ãå©ããšã㯠aspida ã䜿ãããšãå€ãã§ã ãã®èŸºãã®ããŒã«ã¯åå®å
šæ§ã®æ
ä¿ããã¡ããã§ããããã§ã«ååšããã¹ããŒããšåãåãæåã§æžããªããŠè¯ãç¹ãå¬ãããã€ã³ãã§ãã â¡ TS ã®åã§ã¯ãªãã©ã³ã¿ã€ã ãã§ãã¯ãè¡ããç¬èªã®å宣èšãè¡ãã¢ãããŒã TypeScript ã§ã¯åå®çŸ©ããã©ã³ã¿ã€ã ã®ã³ãŒããçæããããšã¯ã§ããŸãã ãªã®ã§åå®çŸ©ãšã¯å¥ã«ã©ã³ã¿ã€ã ãã§ãã¯çšã®åãæžããŠããã§ãã§ãã¯ããããšããã¢ãããŒãã§ã ã©ã³ã¿ã€ã ãã§ãã¯çšã®åã¯ã©ã€ãã©ãªãæå®ããç¬èªã®æžãæ¹ã§å®£èšããå¿
èŠãããã®ã§ãéè€ç®¡çã«ãªãããã«æããããããŸããããå€ãã TS ã®åãåãåºãã®ã¯é£ãããªãã®ã§ãã©ã³ã¿ã€ã ãã§ãã¯çšã®åãã TypeScript ã®åãæŸããããã«ãªã£ãŠããŸã io-ts GitHub - gcanti/io-ts: Runtime type system for IO decoding/encoding èšãããšãããã©ã³ã¿ã€ã åãã§ãã¯ã®ã©ã€ãã©ãªã®çéã§ã io-ts ã®æå®ãã圢ã§åå®çŸ©ãæžããŠã©ã³ã¿ã€ã ãã§ãã¯ãè¡ããŸã // io-ts ã®ãµã³ãã«ã³ãŒã import * as t from 'io-ts' import { isRight } from 'fp-ts/lib/Either' const UserRuntimeType = t. type( { id: t. number , name: t. string , union: t.union ( [ t. string , t. number ] ), optional: t.union ( [ t. string , t. undefined ] ), nullable: t.union ( [ t. string , t. null ] ), } ) type User /* : { id: number; name: string; union: string | number; nullable: string | null; optional?: string | undefined; } */ = t.TypeOf <typeof UserRuntimeType > const maybeUser: unknown = 'invalid' const user = UserRuntimeType.decode ( maybeUser ) if ( isRight ( user )) { // ã©ã³ã¿ã€ã ããªããŒã·ã§ã³ãæåãããšãã ããã®ãããã¯ãéã user.right /* : User ã«åãä»ã */ } isRight ãšãã«é¢æ°åã£ãœããèŠãé ãããŸãã runtypes GitHub - pelotom/runtypes: Runtime validation for static types io-ts ãšåæ§ã«ç¬èªã®æ§æã§ã©ã³ã¿ã€ã ãã§ãã¯ã®åã宣èšããŠãã§ãã¯ããŸã io-ts 㯠fp-ts ã«äŸåããŠããŠæžãæ¹ã颿°åããã¯ã«ãªãã®ã§ã颿°åã«å¯ãã®ã奜ãŸãªãã±ãŒã¹ã§äœ¿ãããå°è±¡ã§ã // runtypes ã®ãµã³ãã«ã³ãŒã import { Number , String , Undefined , Null , Record , Union , Static , } from 'runtypes' const UserRuntimeType = Record ( { id: Number , name: String , union: Union ( String , Number ), optional: Union ( String , Undefined ), nullable: Union ( Null , Undefined ), } ) type User = Static <typeof UserRuntimeType > const maybeUser: unknown = 'invalid' const user = UserRuntimeType.check ( maybeUser ) // ããããã£ãã error ãæãã user /* User ã«åãä»ã */ io-ts 㯠decode æã«åã¬ãŒããè¡ããŸãããruntypes ã§ã¯ããªããŒã·ã§ã³ããŠå€ãããããã£ããäŸå€ãæãããšãã圢ã®ããã§ã superstruct GitHub - ianstormtaylor/superstruct: A simple and composable way to validate data in JavaScript (and TypeScript). ããã¯èªåãç¥ããªãã£ãã©ã€ãã©ãªãªã®ã§ãããçµæ§äººæ°ã®ããã©ã€ãã©ãªãããã¹ã¿ãŒã 5600 ã€ããŠããŸãã Introduction - Superstruct ããã¥ã¡ã³ããããªãå
å®ããŠããŸãã // superstruct ã®ãµã³ãã«ã³ãŒã import { object , number , string , Infer , assert , union , optional , nullable , is , } from 'superstruct' const UserRuntimeType = object ( { id: number (), name: string (), union: union ( [ string (), number () ] ), optional: optional ( string ()), nullable: nullable ( string ()), } ) type User = Infer <typeof UserType > const maybeUser: unknown = 'invalid' if ( is ( maybeUser , UserRuntimeType )) { maybeUser /* User ã«åãä»ã */ } assert ( maybeUser , UserRuntimeType ) // ããªããŒã·ã§ã³ã«å€±æãããäŸå€ãçºç maybeUser /* User ã«åãä»ã */ åã®çµã蟌ã¿ã¯ã¢ãµãŒã·ã§ã³ãšåã¬ãŒãäž¡æ¹ã«å¯Ÿå¿ããŠããããã§ã Utilities - Superstruct Utility types ã«å¯Ÿå¿ãã omit, partial, pick ã䜿ããããã衚çŸåãããªãè±ãããã§å¥œæè§Šã§ãã ã©ã³ã¿ã€ã ãã§ãã¯ã¯ããããã© io-ts ã¯åããªãã£ãŠæ¹ã«ã¯ãã¡ãŒã¹ããã§ã€ã¹ã«ãªãããã§ã zod GitHub - colinhacks/zod: TypeScript-first schema validation with static type inference äžã®2ã€ãšåæ§ã® Zod ãæäŸããããŒã¿åã§ã¹ããŒãã宣èšããŠãã©ã³ã¿ã€ã ãã§ãã¯ãè¡ããŸã // zod ã®ãµã³ãã«ã³ãŒã import { z } from "zod" const UserRuntimeType = z. object ( { id: z. number (), name: z. string (), union: z.union ( [ z. string (), z. number () ] ), optional: z.union ( [ z. string (), z. undefined () ] ), nullable: z.union ( [ z. null (), z. string () ] ), } ) type User = z.infer <typeof UserRuntimeType > const maybeUser: unknown = "invalid" const user = UserRuntimeType.parse ( maybeUser ) // 倱æãããäŸå€ãæãã user /* User ã«åãä»ã */ const result = UserRuntimeType.safeParse ( "invalid" ) if ( result.success ) { maybeUser as User // åã¬ãŒãã¯éå¯Ÿå¿ (unknown ã®ãŸãŸ) ã ãããªããŒã·ã§ã³ã¯ã§ããã®ã§ãåãã£ã¹ãã¯å®å
š } åã¬ãŒãã«ã¯å¯Ÿå¿ããŠãªãããã§ããããªããŒã·ã§ã³èªäœã¯ã§ããã®ã§åãã£ã¹ãã¯äžå¿å®å
šã§ã ãŸãä»åã®å€ã®åã TypeScript ã®åéãããã©ã³ã¿ã€ã ãã§ãã¯ãããšããè¶£æšãšã¯è¥å¹²ãºã¬ãã®ã§è©³ããã¯è§ŠããŸãããã ajv , yup , joi çã®ããªããŒã·ã§ã³ã©ã€ãã©ãªãäœ¿ãææ®µããããŸã ⢠åå®çŸ©ããã©ã³ã¿ã€ã ãã§ãã¯ã®é¢æ°ãèªåçæããã¢ãããŒã â¡ ã®ã¢ãããŒãã§ã¯ TS ã®åãäžæã®åã«ãããç¶æ³ã«ã¯ããŸãé©ããŸãã 䜿ãããšãã§ããªãããã§ã¯ãããŸããããåæ
å ±ãäºé管çã«ãªã£ãŠããŸããŸã å
·äœçã«ã¯ â ã®ã¢ãããŒãã§ TypeScript ã®åãèªåçæããŠããã±ãŒã¹ åŠç¿ã³ã¹ãçã®åé¡ã§ TypeScript ã®åã§å®çŸ©ãããã±ãŒã¹ çã§ã å®è¡æã« TS ã®åããå€ãäœãããšã¯ã§ããŸããããäºåã«åæ
å ±ããã³ãŒãçæãããããšãªãå¯èœãªã®ã§ã³ãŒãçæã«ãã£ãŠå¯Ÿå¿ããããšããã¢ãããŒãã§ã ts-auto-guard GitHub - rhys-vdw/ts-auto-guard: Generate type guard functions from TypeScript interfaces cli ãæäŸãããŠã㊠$ ts-auto-guard ./path/to/type.ts ãããšã type.guard.ts ã«åã¬ãŒã颿°ãçæãããŠã€ã³ããŒãããŠäœ¿ãããšãã§ããããã§ã // ts-auto-guard ã®ãµã³ãã«ã³ãŒã import { isUser } from './type.guard' const maybeUser: unknown = 'invalid' if ( isUser ) { maybeUser /* : User */ } type-predicates-generator GitHub - d-kimuson/type-predicates-generator: generating predicates and assertion function by type definitions. ä»ååãäœã£ãããŒã«ã§ãã詳现㯠玹ä»èšäº ãæžããã°ãããªã®ã§ãã¡ãã«è²ããŸãã watch ãç«ãŠãŠãããåå®çŸ©ã®å€æŽã«ãªã¢ã«ã¿ã€ã ã«è¿œåŸããŠã©ã³ã¿ã€ã ãã§ãã¯é¢æ°ãèªåçæããããšãã§ããŸã $ type-predicates-generator -f 'types/**/*/ts' -o predicates.ts -a -w // type-predicates-generator ã®ãµã³ãã«ã³ãŒã import { isUser , assertIsUser } from '/path/to/predicates' const maybeUser: unknown = 'invalid' if ( isUser ) { maybeUser /* : User */ } assertIsUser ( maybeUser ) maybeUser /* : User */ typescript-is GitHub - woutervh-/typescript-is typescript-is ã¯å°ãç¹æ®ã§ ttypescript ãšãã TypeScript ã«ããã©ã«ã以å€ã® transform åŠçãæãããŒã«ãšã»ããã§äœ¿ãããšã§ããã«ãæã«ã©ã³ã¿ã€ã ãã§ãã¯é¢æ°ãçæããããšãã§ããŸã // typescript-is ã®ãµã³ãã«ã³ãŒã import { is } from 'typescript-is' type User = { id: number name: string } const maybeUser: unknown = 'invalid' if ( is < User >( maybeUser )) { maybeUser } æ¬æ¥ã¯ is<User>() ã®ãããªåœ¢ã§ User åã«åããããããªãã§ãã¯é¢æ°ãäœãããšã¯ã§ããŸããããã«ã¹ã¿ã ãã©ã³ã¹ãã©ãŒããŒã§åã® 2 ã€ãšåããããªã³ãŒãçæããã«ãæã«è¡ãããšã§ãã©ã³ã¹ãã€ã«åŸã®ãã¡ã€ã«ã«ã©ã³ã¿ã€ã ãã§ãã¯ãæžãåºãããšãã§ããŸã äžã® if æã¯ä»¥äžã®ããã«ãã©ã³ã¹ãã€ã«ãããŸã if ( (0, typescript_is_1.is)(maybeUser, object => { function _number(object) { if ( typeof object !== 'number' ) return {} else return null } function _string(object) { if ( typeof object !== 'string' ) return {} else return null } function _0(object) { if ( typeof object !== 'object' || object === null || Array .isArray(object) ) return {} { if ( 'id' in object) { var error = _number(object [ 'id' ] ) if (error) return error } else return {} } { if ( 'name' in object) { var error = _string(object [ 'name' ] ) if (error) return error } else return {} } return null } return _0(object) } ) ) { maybeUser } æšæºã§ã¯ãªã ttsc ã§ãã«ãããå¿
èŠãããããš åãåã«å¯Ÿãããã§ãã¯ãæ¯åé·ã
ãšæžãåºãã®ã§ãã³ãã«ãµã€ãºãå¢ããã¡ ã©ã³ã¿ã€ã ãã§ãã¯ã®å®è£
ãã¢ããããŒãçã§å€ãã£ããšãã«ãœãŒã¹ã³ãŒããããªãã®ã§æ°ã¥ããªã ãšãã£ãæçŽã¯ãããšæããŸãããçŽæçãã€æè»œã«å€ã®åãå®ãããšãã§ããŸã ããŸã: as-safely ããªããã£ãçã®åãæ°è»œã«ãã§ãã¯ããã«ã¯ã as-safely ãšããã©ã€ãã©ãªãæè»œã§ããisString çã®ã©ã³ã¿ã€ã ãã§ãã¯é¢æ°ãæäŸãããŠããŸã import { asSafely , isString } from 'as-safely' const maybeStr: unknown = 'valid' asSafely ( maybeStr , isString ) // ãã§ãã¯ã«å€±æãããäŸå€ãæãã maybeStr /* string ã«åãã€ã */ ã«ã¹ã¿ã ã®ã©ã³ã¿ã€ã ãã§ãã¯é¢æ°ã䜿çšã§ããã®ã§ãâ¡ ã ⢠ã®ã©ã€ãã©ãª/ããŒã«ãšçµã¿åãããŠã¢ãµãŒã·ã§ã³ãæè»œã«è¡ãããšãã§ããŸã äŸãã° ts-auto-guard ã¯ã¢ãµãŒã·ã§ã³é¢æ°ã®èªåçæãæäŸããªãããã§ãããasSafely ãšã»ããã§äœ¿ããšæè»œã«ã¢ãµãŒã·ã§ã³ãè¡ãããšãã§ããŸã import { asSafely } from 'as-safely' import { isUser } from './type.guard' const maybeUser: unknown = 'invalid' asSafely ( maybeUser , isUser ) maybeUser /* : User ã«åãä»ã */ ãŸãšã å€éšãããã£ãŠããå€ã«å®å
šã«åãã€ããæ¹æ³ã«ã€ããŠ3ã€ã®ã¢ãããŒãã«åããŠç޹ä»ããŸããïŒ io-ts ãäžçªæåã ãšæããŸãããããã«éããè€æ°ã®éžæè¢ãããã®ã§ãããžã§ã¯ãã«ãã£ã圢ã§åãå®ãããšè¯ãã®ã§ã¯ãªãã§ãããã å人çã«ã¯ ã¡ãããšããã¹ããŒããããç®æ â â + ⢠ã®ãããæ ããä»¥å€ â â¡ é¢æ°åã£ãœããå
¥ã£ãŠãåé¡ãªã â io-ts ãã£ãšæ®éã®ãè¯ã â superstruct 蟺ãã«ãªãããããªãšããå°è±¡ã§ãã ããã§ã¯è¯ãåå®å
šã©ã€ããïŒ