NestJS âïž class-validatorTipséð

FE Req ãš BE Req ã«å·®åãããå Žåã®ç¢ºèªãã€ã³ãð
ãã®åé¡ã¯ãããã³ããšã³ãïŒFEïŒããããã¯ãšã³ãïŒBEïŒã«ãªã¯ãšã¹ããéä¿¡ããéã«ãããŒã¿ãæ£ããåãåãããªãåå ãããã€ãèããããŸãã
以äžã«ãèããããåå ãšãã®è§£æ±ºçã瀺ããŸãã
1. ããŒã¿ã®é信圢åŒ
ãªã¯ãšã¹ããæ£ãã圢åŒã§éä¿¡ãããŠããã確èªããŠãã ãããç¹ã«ãJSON圢åŒã§ããŒã¿ãéä¿¡ããå Žåãæ£ããããããŒïŒContent-Type: application/json
ïŒãèšå®ãããŠããã確èªããŸãã
2. NestJSã®DTOïŒData Transfer ObjectïŒ
NestJSã§ã¯ããªã¯ãšã¹ãããŒã¿ãåãåãããã«DTOã䜿çšããããšãäžè¬çã§ããUpdateArchiveVideoUploadedReq
ã¯ã©ã¹ãDTOãšããŠæ£ããæ©èœããŠããã確èªããŠãã ããã
ç¹ã«ãclass-validator
ã䜿çšããŠããå ŽåãããªããŒã·ã§ã³ãæ£ããèšå®ãããŠããã確èªããŸãã
import { IsBoolean } from 'class-validator';
export class UpdateFileReq extends FileBaseReq {
@IsBoolean()
isUpdateFile: boolean;
constructor(arg: {
isUpdateFile: boolean;
captionJa: string;
captionEn: string;
descriptionJa: string;
descriptionEn: string;
thumbnailUrl?: string;
displayOrder: number;
}) {
super(arg);
this.displayOrder = arg.displayOrder;
}
}
3. ããã¯ãšã³ãã®åãåãåŽã®èšå®
ããã¯ãšã³ãã§ãªã¯ãšã¹ããåãåãéã«ãæ£ãããšã³ããã€ã³ããèšå®ãããŠãããã
ãŸãããªã¯ãšã¹ãããã£ãæ£ããããŒã¹ãããŠããã確èªããŠãã ããã
@Body()
ãã³ã¬ãŒã¿ãŒã䜿çšããŠããªã¯ãšã¹ãããã£ãæ£ããåãåãããã«ããŸãã
import { Controller, Post, Body } from '@nestjs/common';
@Controller('file')
export class FileController {
@Post('update')
async updateFile(@Body() updateReq: UpdateFileReq) {
// ããã§updateReqã䜿çšããŠåŠçãè¡ã
}
}
4. ããã³ããšã³ãã®ããŒã¿æ§é
ããã³ããšã³ãããéä¿¡ããããŒã¿ããããã¯ãšã³ãã§æåŸ ãããæ§é ãšäžèŽããŠããã確èªããŠãã ãããç¹ã«ããªããžã§ã¯ãã®ããããã£åãåãäžèŽããŠãããã確èªããŸãã
5. ãšã©ãŒãã³ããªã³ã°
ãªã¯ãšã¹ãã倱æããå Žåããšã©ãŒã¡ãã»ãŒãžãã¬ã¹ãã³ã¹ã確èªããŠãã©ã®éšåã§åé¡ãçºçããŠããããç¹å®ããŸãã
NestJSã®ãããã°æ©èœã䜿çšããŠããªã¯ãšã¹ãã®æµãã远跡ããããšãæå¹ã§ãã
ãããã®ãã€ã³ãã確èªããåé¡ãç¹å®ããŠä¿®æ£ããããšã§ãããŒã¿ãæ£ããåãåããããã«ãªãã¯ãã§ãã
åèã»åŒçš

NestJSãšDTO (Data Transfer Object)ã«ã€ããŠ
NestJSã§ã¯ãã¯ã©ã¹ãçšããŠDTOãå®çŸ©ããŸãã
ãŸããclass-validatorãšclass-transformerããã±ãŒãžã䜿çšããŠãããªããŒã·ã§ã³ãšããŒã¿ã®å€æãè¡ããŸãã

[Nest.js] class-validatorã䜿ã£ãŠã«ã¹ã¿ã ããªããŒã·ã§ã³ãäœæããã«ã¯

class-validator ã® Validation decorator ããŒãã·ãŒã ð
class-validator ã«æšæºæèŒãããŠããããªããŒã·ã§ã³ã»ãã³ã¬ãŒã¿ãŒã®çš®é¡ã¯ãclass-validator ã® README.md ã«æŽçãããŠããŸãã
äžèšãREADME.md ã«èšèŒããŠãããã®ã翻蚳ããŠæŽçããŸãã ð
以äžã®ãšãããã«ããŽãªããšã« Markdown ã®ããŒãã«åœ¢åŒã§ãŸãšããŸããã
äžè¬çãªæ€èšŒãã³ã¬ãŒã¿
ãã³ã¬ãŒã¿ãŒ | 説æ |
---|---|
@IsDefined(value: any) |
å€ãå®çŸ©ãããŠãããã©ããã確èªããŸã (!== undefinedã!== null)ããã㯠skipMissingProperties ãªãã·ã§ã³ãç¡èŠããå¯äžã®ãã³ã¬ãŒã¿ã§ãã |
@IsOptional() |
æå®ãããå€ã空 (=== nullã=== undefined) ãã©ããã確èªãã空ã®å Žåã¯ããããã£ã®ãã¹ãŠã®æ€èšŒãç¡èŠããŸãã |
@Equals(comparison: any) |
å€ãçãããã©ãã ("===") æ¯èŒããŠãã§ãã¯ããŸãã |
@NotEquals(comparison: any) |
å€ãçãããªããã©ãã ("!==") æ¯èŒããã§ãã¯ããŸãã |
@IsEmpty() |
æå®ãããå€ã空ãã©ããã確èªããŸã (=== '', === null, === undefined)ã |
@IsNotEmpty() |
æå®ãããå€ã空ã§ãªããã©ããã確èªããŸã (!== '', !== null, !== undefined)ã |
@IsIn(values: any[]) |
å€ãèš±å¯ãããå€ã®é åå ã«ãããã©ããã確èªããŸãã |
@IsNotIn(values: any[]) |
å€ãèš±å¯ãããªãå€ã®é åã«å«ãŸããŠããªããã©ããã確èªããŸãã |
åæ€èšŒãã³ã¬ãŒã¿
ãã³ã¬ãŒã¿ãŒ | 説æ |
---|---|
@IsBoolean() |
å€ãããŒã«å€ãã©ããã確èªããŸãã |
@IsDate() |
å€ãæ¥ä»ãã©ããã確èªããŸãã |
@IsString() |
å€ãæååãã©ããã確èªããŸãã |
@IsNumber(options: IsNumberOptions) |
å€ãæ°å€ãã©ããã確èªããŸãã |
@IsInt() |
å€ãæŽæ°ãã©ããã確èªããŸãã |
@IsArray() |
å€ãé åãã©ããããã§ãã¯ããŸãã |
@IsEnum(entity: object) |
å€ãæå¹ãªåæåãã©ããã確èªããŸãã |
æ°å€æ€èšŒãã³ã¬ãŒã¿
ãã³ã¬ãŒã¿ãŒ | 説æ |
---|---|
@IsDivisibleBy(num: number) |
å€ãå¥ã®æ°å€ã§å²ãåããæ°å€ãã©ããã確èªããŸãã |
@IsPositive() |
å€ããŒããã倧ããæ£ã®æ°ãã©ããã確èªããŸãã |
@IsNegative() |
å€ããŒãããå°ããè² ã®æ°ãã©ããã確èªããŸãã |
@Min(min: number) |
æå®ãããæ°å€ãæå®ãããæ°å€ä»¥äžã§ãããã©ããã確èªããŸãã |
@Max(max: number) |
æå®ãããæ°å€ãæå®ãããæ°å€ä»¥äžãã©ããã確èªããŸãã |
æ¥ä»æ€èšŒãã³ã¬ãŒã¿
ãã³ã¬ãŒã¿ãŒ | 説æ |
---|---|
@MinDate(date: Date | (() => Date)) |
å€ãæå®ãããæ¥ä»ä»¥éã®æ¥ä»ã§ãããã©ããã確èªããŸãã |
@MaxDate(date: Date | (() => Date)) |
å€ãæå®ãããæ¥ä»ããåã®æ¥ä»ã§ãããã©ããã確èªããŸãã |
æåååæ€èšŒãã³ã¬ãŒã¿
ãã³ã¬ãŒã¿ãŒ | 説æ |
---|---|
@IsBooleanString() |
æååãããŒã«å€ã§ãããã©ããã確èªããŸã (äŸ: ãtrueããŸãã¯ãfalseããŸãã¯ã1ããã0ã)ã |
@IsDateString() |
@IsISO8601() ã®ãšã€ãªã¢ã¹ã |
@IsNumberString(options?: IsNumericOptions) |
æååãæ°å€ãã©ããã確èªããŸãã |

äžèšã®ç¶ãð
æååæ€èšŒãã³ã¬ãŒã¿
ãã³ã¬ãŒã¿ãŒ | 説æ |
---|---|
@Contains(seed: string) |
æååã«ã·ãŒããå«ãŸããŠãããã©ããã確èªããŸãã |
@NotContains(seed: string) |
æååã«ã·ãŒããå«ãŸããŠããªããã©ããã確èªããŸãã |
@IsAlpha() |
æååã«æå (a-zA-Z) ã®ã¿ãå«ãŸããŠãããã©ããã確èªããŸãã |
@IsAlphanumeric() |
æååã«æåãšæ°åã®ã¿ãå«ãŸããŠãããã©ããã確èªããŸãã |
@IsDecimal(options?: IsDecimalOptions) |
æååãæå¹ãª 10 鲿°å€ã§ãããã©ããã確èªããŸãã ããã©ã«ãã® IsDecimalOptions 㯠force_decimal=false, decimal_digits: '1,', locale: 'en-US' ã |
@IsAscii() |
æååã« ASCII æåã®ã¿ãå«ãŸããŠãããã©ããã確èªããŸãã |
@IsBase32() |
æååã base32 ã§ãšã³ã³ãŒããããŠãããã©ããã確èªããŸãã |
@IsBase58() |
æååã base58 ã§ãšã³ã³ãŒããããŠãããã©ããã確èªããŸãã |
@IsBase64(options?: IsBase64Options) |
æååã base64 ã§ãšã³ã³ãŒããããŠãããã©ããã確èªããŸãã |
@IsIBAN() |
æååã IBAN (åœééè¡å£åº§çªå·) ã§ãããã©ããã確èªããŸãã |
@IsBIC() |
æååã BIC (éè¡èå¥ã³ãŒã) ãŸã㯠SWIFT ã³ãŒãã§ãããã©ããã確èªããŸãã |
@IsByteLength(min: number, max?: number) |
æååã®é·ã (ãã€ãåäœ) ãç¯å²å ã«ãããã©ããã確èªããŸãã |
@IsCreditCard() |
æååãã¯ã¬ãžããã«ãŒããã©ããã確èªããŸãã |
@IsCurrency(options?: IsCurrencyOptions) |
æååãæå¹ãªé貚éé¡ã§ãããã©ããã確èªããŸãã |
@IsISO4217CurrencyCode() |
æååã ISO 4217 é貚ã³ãŒãã§ãããã©ããã確èªããŸãã |
@IsEthereumAddress() |
åºæ¬çãªæ£èŠè¡šçŸã䜿çšããŠãæååã Ethereum ã¢ãã¬ã¹ã§ãããã©ããã確èªããŸãã ã¢ãã¬ã¹ã®ãã§ãã¯ãµã ã¯æ€èšŒããŸããã |
@IsBtcAddress() |
æååãæå¹ãª BTC ã¢ãã¬ã¹ã§ãããã©ããã確èªããŸãã |
@IsDataURI() |
æååãããŒã¿ URI 圢åŒã§ãããã©ããã確èªããŸãã |
@IsEmail(options?: IsEmailOptions) |
æååãé»åã¡ãŒã«ã§ãããã©ããã確èªããŸãã |
@IsFQDN(options?: IsFQDNOptions) |
æååãå®å šä¿®é£Ÿãã¡ã€ã³å (äŸ: domain.com) ã§ãããã©ããã確èªããŸãã |
@IsFullWidth() |
æååã«å šè§æåãå«ãŸããŠãããã©ããã確èªããŸãã |
@IsHalfWidth() |
æååã«åè§æåãå«ãŸããŠãããã©ããã確èªããŸãã |
@IsVariableWidth() |
æååã«å šè§æåãšåè§æåãæ··åšããŠãããã©ããã確èªããŸãã |
@IsHexColor() |
æååã 16 鲿°ã®è²ã§ãããã©ããã確èªããŸãã |
@IsHSL() |
æååã CSS ã«ã©ãŒ ã¬ãã« 4 仿§ã«åºã¥ã HSL ã«ã©ãŒã§ãããã©ããã確èªããŸãã |
@IsRgbColor(options?: IsRgbOptions) |
æååã rgb ã«ã©ãŒã rgba ã«ã©ãŒãã確èªããŸãã |
@IsIdentityCard(locale?: string) |
æååãæå¹ãª ID ã«ãŒã ã³ãŒãã§ãããã©ããã確èªããŸãã |
@IsPassportNumber(countryCode?: string) |
æååãç¹å®ã®åœã³ãŒãã«é¢é£ããæå¹ãªãã¹ããŒãçªå·ã§ãããã©ããã確èªããŸãã |
@IsPostalCode(locale?: string) |
æååãéµäŸ¿çªå·ãã©ããã確èªããŸãã |
@IsHexadecimal() |
æååã 16 鲿°ã§ãããã©ããã確èªããŸãã |
@IsOctal() |
æååã 8 鲿°ã§ãããã©ããã確èªããŸãã |
@IsMACAddress(options?: IsMACAddressOptions) |
æååã MAC ã¢ãã¬ã¹ã§ãããã©ããã確èªããŸãã |
@IsIP(version?: "4"|"6") |
æååã IP (ããŒãžã§ã³ 4 ãŸã㯠6) ã§ãããã©ããã確èªããŸãã |
@IsPort() |
æååãæå¹ãªããŒãçªå·ã§ãããã©ããã確èªããŸãã |
@IsISBN(version?: "10"|"13") |
æååã ISBN (ããŒãžã§ã³ 10 ãŸã㯠13) ã§ãããã©ããã確èªããŸãã |
@IsEAN() |
æååã EAN (欧å·ååçªå·) ã§ãããã©ããã確èªããŸãã |
@IsISIN() |
æååã ISIN (æ ªåŒ/蚌åžèå¥å) ã§ãããã©ããã確èªããŸãã |
@IsISO8601(options?: IsISO8601Options) |
æååãæå¹ãª ISO 8601 æ¥ä»åœ¢åŒã§ãããã©ããã確èªããŸãã æå¹ãªæ¥ä»ã®è¿œå ãã§ãã¯ã«ã¯ããªãã·ã§ã³ strict = true ã䜿çšããŸãã |
@IsJSON() |
æååãæå¹ãª JSON ãã©ããã確èªããŸãã |
@IsJWT() |
æååãæå¹ãª JWT ãã©ããã確èªããŸãã |
@IsObject() |
ãªããžã§ã¯ããæå¹ãªãªããžã§ã¯ãã§ãããã©ããã確èªããŸã (nullã颿°ãé å㯠false ãè¿ããŸã)ã |
@IsNotEmptyObject() |
ãªããžã§ã¯ãã空ã§ãªããã©ããã確èªããŸãã |
@IsLowercase() |
æååãå°æåãã©ããã確èªããŸãã |
@IsLatLong() |
æååã lat, long 圢åŒã®æå¹ãªç·¯åºŠçµåºŠåº§æšã§ãããã©ããã確èªããŸãã |
@IsLatitude() |
æååãŸãã¯æ°å€ãæå¹ãªç·¯åºŠåº§æšã§ãããã©ããã確èªããŸãã |
@IsLongitude() |
æååãŸãã¯æ°å€ãæå¹ãªçµåºŠåº§æšã§ãããã©ããã確èªããŸãã |
@IsMobilePhone(locale: string) |
æååãæºåž¯é»è©±çªå·ãã©ããã確èªããŸãã |
@IsISO31661Alpha2() |
æååãæå¹ãª ISO 3166-1 alpha-2 ã«æ£åŒã«å²ãåœãŠãããåœã³ãŒãã§ãããã©ããã確èªããŸãã |
@IsISO31661Alpha3() |
æååãæå¹ãª ISO 3166-1 alpha-3 ã«æ£åŒã«å²ãåœãŠãããåœã³ãŒãã§ãããã©ããã確èªããŸãã |
@IsLocale() |
æååããã±ãŒã«ã§ãããã©ããã確èªããŸãã |
@IsPhoneNumber(region: string) |
libphonenumber-js ã䜿çšããŠãæååãæå¹ãªé»è©±çªå·ã§ãããã©ããã確èªããŸãã |
@IsMongoId() |
æååã MongoDB ObjectId ã®æå¹ãª 16 é²ãšã³ã³ãŒã衚çŸã§ãããã©ããã確èªããŸãã |
@IsMultibyte() |
æååã« 1 ã€ä»¥äžã®ãã«ããã€ãæåãå«ãŸããŠãããã©ããã確èªããŸãã |
@IsNumberString(options?: IsNumericOptions) |
æååãæ°å€ãã©ããã確èªããŸãã |
@IsSurrogatePair() |
æååã«ãµãã²ãŒããã¢æåãå«ãŸããŠãããã©ããã確èªããŸãã |
@IsTaxId() |
æååãæå¹ãªçŽçšè
çªå·ã§ãããã©ããã確èªããŸãã ããã©ã«ãã®ãã±ãŒã«ã¯ en-US ã§ãã |
@IsUrl(options?: IsURLOptions) |
æååã URL ã§ãããã©ããã確èªããŸãã |
@IsMagnetURI() |
æååããã°ããã URI 圢åŒã§ãããã©ããã確èªããŸãã |
@IsUUID(version?: UUIDVersion) |
æååã UUID (ããŒãžã§ã³ 3ã4ã5ããŸãã¯ãã¹ãŠ) ã§ãããã©ããã確èªããŸãã |
@IsFirebasePushId() |
æååã Firebase Push ID ã§ãããã©ããã確èªããŸãã |
@IsUppercase() |
æååã倧æåãã©ããã確èªããŸãã |
@Length(min: number, max?: number) |
æååã®é·ããç¯å²å ã«ãããã©ããã確èªããŸãã |
@MinLength(min: number) |
æååã®é·ããæå®ãããæ°å€ããå°ãããªããã©ããã確èªããŸãã |
@MaxLength(max: number) |
æååã®é·ããæå®ãããæ°å€ä»¥äžãã©ããã確èªããŸãã |
@Matches(pattern: RegExp, modifiers?: string) |
æååããã¿ãŒã³ã«äžèŽãããã©ããã確èªããŸããmatches('foo', /foo/i) ãŸã㯠matches('foo', 'foo', 'i') ã®ããããã |
@IsMilitaryTime() |
æååã HH:MM 圢åŒã® 24 æé衚èšãšããŠæå¹ãã©ããã確èªããŸãã |
@IsTimeZone() |
æååãæå¹ãª IANA ã¿ã€ã ãŸãŒã³ã衚ããŠãããã©ããã確èªããŸãã |
@IsHash(algorithm: string) |
æååãããã·ã¥ã§ãããã©ããã確èªããŸãã ãµããŒããããŠããã¿ã€ã: md4, md5, sha1, sha256, sha384, sha512, ripemd128, ripemd160, tiger128, tiger160, tiger192, crc32, crc32b
|
@IsMimeType() |
æååãæå¹ãª MIME ã¿ã€ã圢åŒã«äžèŽãããã©ããã確èªããŸãã |
@IsSemVer() |
æååãã»ãã³ãã£ã㯠ããŒãžã§ã³æå® (SemVer) ã§ãããã©ããã確èªããŸãã |
@IsISSN(options?: IsISSNOptions) |
æååã ISSN ã§ãããã©ããã確èªããŸãã |
@IsISRC() |
æååã ISRC ã§ãããã©ããã確èªããŸãã |
@IsRFC3339() |
æååãæå¹ãª RFC 3339 æ¥ä»ã§ãããã©ããã確èªããŸãã |
@IsStrongPassword(options?: IsStrongPasswordOptions) |
æååã匷åãªãã¹ã¯ãŒãã§ãããã©ããã確èªããŸãã |
é åæ€èšŒãã³ã¬ãŒã¿
ãã³ã¬ãŒã¿ãŒ | 説æ |
---|---|
@ArrayContains(values: any[]) |
é åã«æå®ãããå€ã®é åã®ãã¹ãŠã®å€ãå«ãŸããŠãããã©ããã確èªããŸãã |
@ArrayNotContains(values: any[]) |
é åã«æå®ãããå€ãå«ãŸããŠããªããã©ããã確èªããŸãã |
@ArrayNotEmpty() |
æå®ãããé åã空ã§ãªããã©ããã確èªããŸãã |
@ArrayMinSize(min: number) |
é åã®é·ããæå®ãããæ°ä»¥äžã§ãããã©ããã確èªããŸãã |
@ArrayMaxSize(max: number) |
é åã®é·ããæå®ãããæ°ä»¥äžãã©ããã確èªããŸãã |
@ArrayUnique(identifier?: (o) => any) |
ãã¹ãŠã®é
åã®å€ãäžæã§ãããã©ããã確èªããŸãã ãªããžã§ã¯ãã®æ¯èŒã¯åç §ããŒã¹ã§è¡ãããŸãã æ¯èŒã«äœ¿çšãããæ»ãå€ããªãã·ã§ã³ã§æå®ã§ããŸãã |
ãªããžã§ã¯ãæ€èšŒãã³ã¬ãŒã¿
ãã³ã¬ãŒã¿ãŒ | 説æ |
---|---|
@IsInstance(value: any) |
ããããã£ãæž¡ãããå€ã®ã€ã³ã¹ã¿ã³ã¹ã§ãããã©ããã確èªããŸãã |
ãã®ä»ã®ãã³ã¬ãŒã¿ãŒ
ãã³ã¬ãŒã¿ãŒ | 説æ |
---|---|
@Allow() |
ä»ã®å¶çŽãæå®ãããŠããªãå Žåã«ããããã£ãåé€ãããã®ãé²ããŸãã |

æ€èšŒãšã©ãŒ: validate ãš ValidationError
class-validator ã®æ€èšŒé¢æ°ã§ããvalidate
ã¡ãœããã¯ãValidationError
Class ã®é
åãè¿ããŸãã
ã¡ãªã¿ã«ValidationError
ã®æ§é ã¯ã次ã®ããã«ãªã£ãŠããŸãã
export declare class ValidationError {
target: object; // ããªããŒã·ã§ã³å¯Ÿè±¡ãšãªã£ããªããžã§ã¯ã
property: string; // ããªããŒã·ã§ã³ã«å€±æããããããã£å
value: any; // ããªããŒã·ã§ã³ã«å€±æããå€
// ã©ã®ããªããŒã·ã§ã³ã倱æããããšããã®ãšã©ãŒã¡ãã»ãŒãžã®ãããã³ã°
constraints?: {
[type: string]: string;
};
children?: ValidationError[]; // ãã¹ããããåããããã£ã®ããªããŒã·ã§ã³ãšã©ãŒãããå Žåã®é
å
contexts?: {
[type: string]: any;
};
}

æ€èšŒã¡ãã»ãŒãžã®ã«ã¹ã¿ãã€ãº
ãã³ã¬ãŒã¿ãŒã®ãªãã·ã§ã³ã§æ€èšŒã¡ãã»ãŒãžãæå®ããããšã§ãæ€èšŒã¡ãã»ãŒãžãã«ã¹ã¿ãã€ãºããããšãã§ããŸãã
(ãã£ãŒã«ãã®æ€èšŒã倱æããå Žåãèšå®ããã¡ãã»ãŒãžãvalidate
ã¡ãœããã«ãã£ãŠè¿ãããŸã)
éçã¡ãã»ãŒãžã®æå®: message
次ã®ããã«ããã³ã¬ãŒã¿ãŒã® Option ã«message
ã远å ããããšãã§ããŸãã
import { MinLength, MaxLength } from "class-validator";
export class Post {
@MinLength(10, {
message: "ã¿ã€ãã«ãçãããŸãïŒæäœ10æåïŒ",
})
@MaxLength(50, {
message: "ã¿ã€ãã«ãé·ãããŸãïŒæå€§50æåïŒ",
})
title: string;
}
åçãªã¡ãã»ãŒãžäœæ: message()
次ã®ããã«ããã³ã¬ãŒã¿ãŒã® Option ã«message()
ã远å ããããšãã§ããŸãã
message()
ã¯ãValidationArguments
ãåŒæ°ã§åãåããŸãã
import { MinLength, MaxLength, ValidationArguments } from "class-validator";
export class Post {
@MinLength(10, {
message: (args: ValidationArguments) => {
if (args.value.length === 1) {
return "çãããŸããæå°æåæ°ã¯ 1 æåã§ãã";
} else {
return "çãããŸããæå°ã®é·ãã¯" + args.constraints[0] + " æåã§ãã";
}
},
})
title: string;
}
ValidationArguments
ã®æ§é ã¯ã次ã®ããã«ãªã£ãŠããŸãã
export interface ValidationArguments {
value: any; // æ€èšŒãããå€
constraints: any[]; // ç¹å®ã®æ€èšŒã¿ã€ãã«ãã£ãŠå®çŸ©ãããå¶çŽã®é
å
targetName: string; // æ€èšŒããããªããžã§ã¯ãã®ã¯ã©ã¹å
object: object; // æ€èšŒäžã®ãªããžã§ã¯ã
property: string; // æ€èšŒããããªããžã§ã¯ãã®ããããã£ã®åå
}
ãã®ä»ã®æ€èšŒã¡ãã»ãŒãžã®ã«ã¹ã¿ã æ¹æ³ã«ã€ããŠã¯ããã¡ãã«è©³çްãªèšèŒããããŸãã

é åããã¹ãããããªããžã§ã¯ãã®æ€èšŒ
é
åå
ã®åé
ç®ã®æ€èšŒãå®è¡ããå Žåã¯ãeach: true
ãªãã·ã§ã³ãæå®ããå¿
èŠããããŸãã
import { MinLength, MaxLength } from "class-validator";
export class Post {
@MaxLength(20, {
each: true,
})
tags: string[];
}
ãã¹ãããããªããžã§ã¯ãã®æ€èšŒ
ãªããžã§ã¯ãã«ãã¹ãããããªããžã§ã¯ããå«ãŸããŠãããããªããŒã¿ãŒã§ãããã®æ€èšŒãå®è¡ãããå Žåã¯ã@ValidateNested()
ãã³ã¬ãŒã¿ãŒã䜿çšããå¿
èŠããããŸãã
ãŸãããã¹ãããããªããžã§ã¯ãã¯ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ã§ããå¿ èŠãããããšã«æ³šæããŠãã ããã
import { ValidateNested } from "class-validator";
export class Post {
@ValidateNested()
user: User;
}
é åå ã®ãã¹ãããããªããžã§ã¯ãã®æ€èšŒ
import { Type } from "class-transformer";
import {
IsArray,
IsNotEmpty,
ValidateNested,
} from "class-validator";
class PostReq {
@IsNotEmpty()
title: string;
@IsEmail()
email: string;
}
@IsArray()
@IsNotEmpty({
message: "空é
åã¯ãNG!",
})
@ValidateNested({ each: true })
@Type(() => PostReq)
readonly posts: PostReq[];

æ¡ä»¶ä»ãæ€èšŒ: @ValidateIf
@ValidateIf
ã䜿ããšããããæ¡ä»¶ãæç«ããå Žåã ããç¹å®ã®ããªããŒã·ã§ã³ãå®è¡ããããšãã§ããŸãã
æ¡ä»¶ã®å€å®çµæãfalse
ã®å Žåã¯ãããªããŒã·ã§ã³èªäœãã¹ããããããããããšã©ãŒãçºçããŸããã
ãã©ãŒã å ¥åãèšå®é ç®ãªã©ããæ¡ä»¶æ¬¡ç¬¬ã§å¿ é ãã©ãããå€ãããã±ãŒã¹ãªã©ã§ãæè»ã«äœ¿ãããã³ã¬ãŒã¿ãŒã«ãªããŸãïŒ
import { ValidateIf, IsNotEmpty } from "class-validator";
export class Post {
isCat: string;
// isCat ã®æã ããå¿
é ãšãªãã
@ValidateIf((o) => o.isCat)
@IsNotEmpty({
message: "å¿
é å
¥åã§ãã",
})
mya: string;
}
æ¡ä»¶ä»ãæ€èšŒã¯ããã¡ã€ã³ããžãã¯ã«äŸåããããªããŒã·ã§ã³ãå®è£ ããã®ã«é©ããŠããŸãã

ãã³ã¬ãŒã¿ãŒã®éãåãã
ãã³ã¬ãŒã¿ãŒã¯éãåãããŠã1 ã€ã®ããããã£ã«å¯ŸããŠè€æ°ã®ããªããŒã·ã§ã³ãã³ã¬ãŒã¿ãŒã䜵çšããããšãã§ããŸãã
(è€æ°ã®ããªããŒã·ã§ã³ãå®è¡ããããšãã§ããŸã)
äŸãã°ã次ã®ãããªã¡ãŒã«ã¢ãã¬ã¹ã®ããªããŒã·ã§ã³ãèããŠã¿ãŸãã
- æªå ¥åã§ãªãããš
- 256 æå以å ã§ããããš
- ASCII æåã§ããããš
- ã¡ãŒã«ã¢ãã¬ã¹åœ¢åŒã§ããããš
äžèšã®æ¡ä»¶ããã¹ãŠæºãããŠããå Žåã¯ãã¡ãŒã«ã¢ãã¬ã¹ãšããŠæå¹ã§ãããšå€å®ããŠããåŠçã«ãªããŸãã
import { IsAscii, IsEmail, IsNotEmpty, MaxLength } from "class-validator";
export class MailCheckReq {
@IsNotEmpty({
message: "æªå
¥åã§ã",
})
@MaxLength(256, {
message: "{{constraint1}}æåãŸã§ã§ã",
context: { constraint1: 256 },
})
@IsAscii({
message: "äžæ£ãªå€ã§ã",
})
@IsEmail(
{},
{
message: "äžæ£ãªå€ã§ã",
}
)
email!: string;
constructor(email: string) {
this.email = email;
}
}

class-validator ã®ã«ã¹ã¿ã ããªããŒã¿ãŒ (ã«ã¹ã¿ã æ€èšŒã¯ã©ã¹/ã«ã¹ã¿ã æ€èšŒãã³ã¬ãŒã¿ãŒ)
class-validator ã®æäŸããæšæºçãªãã³ã¬ãŒã¿ãŒã§å¯Ÿå¿ã§ããªãããªããŒã·ã§ã³ã»ãã¿ãŒã³ã®å Žåã¯ãã«ã¹ã¿ã ããªããŒã¿ãŒãäœæããããšãã§ããŸãã
ã«ã¹ã¿ã æ€èšŒã«ã¯å€§ããåããŠä»¥äžã® 2 ãã¿ãŒã³ããããŸãã
- ã«ã¹ã¿ã æ€èšŒã¯ã©ã¹ãäœæããŠã
@Validate
ãã³ã¬ãŒã¿ãŒããåŒã³åºãã - ã«ã¹ã¿ã æ€èšŒãã³ã¬ãŒã¿ãŒãäœæããŠããã³ã¬ãŒã¿ãŒãšããŠäœ¿ãã
ã«ã¹ã¿ã æ€èšŒã¯ã©ã¹
ã«ã¹ã¿ã æ€èšŒã¯ã©ã¹ã¯ã@ValidatorConstraint
ãã³ã¬ãŒã¿ãŒãšValidatorConstraintInterface
ã®ã€ã³ã¿ãŒãã§ãŒã¹ã䜿çšããŠäœæããŸãã
import {
ValidatorConstraint,
ValidatorConstraintInterface,
} from "class-validator";
// ã«ã¹ã¿ã æ€èšŒã¯ã©ã¹,
// name: isCat ãšããååã§ç»é² (ãšã©ãŒæã® ValidationError ã® constraints ã®ããŒåãšããŠäœ¿ãããŸã)
@ValidatorConstraint({ name: "isCat", async: false })
export class IsCatConstraint implements ValidatorConstraintInterface {
// ããªããŒã·ã§ã³ã®ããžãã¯
validate(text: string) {
return text === "cat";
}
// ããªããŒã·ã§ã³ãšã©ãŒæã«è¡šç€ºãããã¡ãã»ãŒãž
defaultMessage(validationArguments?: ValidationArguments): string {
return "æåå㯠cat ã§ãªããã°ãªããŸãã";
}
}
ã«ã¹ã¿ã æ€èšŒã¯ã©ã¹ã¯ã@Validate
ãã³ã¬ãŒã¿ãŒã䜿ã£ãŠåŒã³åºãããšãã§ããŸãã
import { Validate } from "class-validator";
@Validate(IsCatConstraint)
export class CatReq {
@IsNotEmpty()
name: string;
}
ã«ã¹ã¿ã æ€èšŒãã³ã¬ãŒã¿ãŒ
ã«ã¹ã¿ã æ€èšŒãã³ã¬ãŒã¿ãŒã¯ãregisterDecorator
ã¡ãœããã䜿çšããŠäœæããŸãã
import {
registerDecorator,
ValidationArguments, // validate ã defaultMessage ã¡ãœããã®åŒæ°ãšããŠäžããããã³ã³ããã¹ãæ
å ±ã
ValidationOptions, // ãšã©ãŒã¡ãã»ãŒãžãåçš®èšå®ãè¡ãããã®ãªããžã§ã¯ããåãåãåã§ãã
} from "class-validator";
/**
* IsCat ã«ã¹ã¿ã ãã³ã¬ãŒã¿ãŒ
*
* @param validationOptions ããªããŒã·ã§ã³ãªãã·ã§ã³ (ã¡ãã»ãŒãžãåçš®èšå®ãæå®å¯èœ)
*/
export function IsCat(validationOptions?: ValidationOptions) {
return function (object: Object, propertyName: string) {
registerDecorator({
name: "isCat", // ã«ã¹ã¿ã ãã³ã¬ãŒã¿ãŒã®åå
target: object.constructor, // ãã³ã¬ãŒã¿ãŒãä»äžãããã¯ã©ã¹
propertyName: propertyName, // ãã³ã¬ãŒã¿ãŒãä»äžãããããããã£å
options: validationOptions, // ããªããŒã·ã§ã³æã®ãªãã·ã§ã³
validator: {
/**
* ããªããŒã·ã§ã³ããžãã¯
* å€ã cat ãšäžèŽãããã©ããããã§ãã¯
*/
validate(value: any, args: ValidationArguments): boolean {
return value === "cat";
},
/**
* ããªããŒã·ã§ã³ãšã©ãŒæã®ããã©ã«ãã¡ãã»ãŒãž
*/
defaultMessage(args: ValidationArguments): string {
return "æåå㯠cat ã§ãªããã°ãªããŸãã";
},
},
});
};
}
ã«ã¹ã¿ã æ€èšŒãã³ã¬ãŒã¿ãŒã¯ãå®çŸ©ãããã³ã¬ãŒã¿ãŒå(ex:@IsCat
)ã§åŒã³åºãããšãã§ããŸãã
import { IsCat } from "./IsCat";
export class CatReq {
@IsNotEmpty()
@IsCat()
name: string;
}

class-validator ãš class-transformer ã®é¢ä¿æ§
class-transformer ã¯ãclass-validator ãšã»ããã§äœ¿çšãããããšãå€ãã®ã§ããã®é¢ä¿æ§ã«ã€ããŠæŽçããŠãããŸãã
(class-transformer ã ãã§ããã¶ãèšäº 1 æ¬æžããã®ã§ããã®ãã¡èšäºãæžããããšæããŸã ð)
class-transformer ã¯ããã¬ãŒã³ãªããžã§ã¯ããã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ã«å€æãããããã®éãè¡ã£ããããããã®ã©ã€ãã©ãªã§ãã
äŸãã°ãForm ã®ãã¬ãŒã³ãªããžã§ã¯ãããRequest ã®ã¯ã©ã¹ã«å€æããããããAPI ã®ã¬ã¹ãã³ã¹ããResponse ã®ã¯ã©ã¹ã«å€æãããããªã©ã«äœ¿çšãããŸãã
class-validator ãå©çšããã«ã¯ãClass ã§ããå¿ èŠãããããããã¬ãŒã³ãªããžã§ã¯ããã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ã«å€æããããã«ãclass-transformer ãå©çšããããšãå€ãã§ãã
(Class ã«ããªããŒã·ã§ã³ãã³ã¬ãŒã¿ãŒãä»äžããŠããã°ãclass-transformer ã§ã® Class 倿ã®éã«ãããªããŒã·ã§ã³ã§æ€èšŒããããšãã§ããŸã)
ã¡ãªã¿ã«ãclass-validator ãš class-transformer ã¯ãã©ã¡ãã typestack ãšããããã±ãŒãžã§æäŸãããŠããããã±ãŒãžã§ãã

class-validator ã®ãã³ã¬ãŒã¿ãŒã«ã€ããŠ
class-validator ã®æŠèŠãšç¹åŸŽãçè§£ããŠããã£ããšããã§ã
class-validator ã®åãã³ã¬ãŒã¿ãŒçŸ€ãã©ã®ãããªç¹åŸŽãæã£ãŠããããç°¡æœã«èª¬æããŠãããŸãã
class-validator ã«æšæºæèŒãããŠããããªããŒã·ã§ã³ã»ãã³ã¬ãŒã¿ãŒã®çš®é¡ã¯ãREADME.md ã«æŽçãããŠãããšããã8 çš®é¡ã«åããããŸã ð
- Common validation decorators: ååšã空ãã©ãããåæãã§ãã¯ãªã©ã®æ±çšçãªæ€èšŒãããã
- Type validation decorators: 察象ã®ããããã£ãæ°å€ãæååãåæåãé åãªã©æ£ããåããªã©ãæ€èšŒããã
- Number validation decorators: æ°å€ãæ£/è² ãæå°ã»æå€§ã®ç¯å²ãç¹å®ã®æ°ã§å²ãåããããªã©ãæ€èšŒããã
- Date validation decorators: æ¥ä»ãæå®ç¯å²å ã«ããããªã©ãæ€èšŒããã
- String-type validation decorators: ããŒã«å€ãæ°å€ãæ¥ä»ãšããŠæå¹ããªã©ãæååã®åœ¢åŒããåãšããŠæ€èšŒããã
- String validation decorators : EmailãURLãUUIDãæ£èŠè¡šçŸãªã©ãæååã®ãã©ãŒããããå³å¯ã«æ€èšŒããã
- Array validation decorators: é åã®èŠçŽ æ°ãéè€ãèŠçŽ ã®å å«ãªã©ãæ€èšŒããã
- Object validation decorators: æå®ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãããã¹ãããããªããžã§ã¯ãã®æ€èšŒãããã
ãããã®æ€èšŒãã³ã¬ãŒã¿ãŒãçµã¿åãããããšã§ããã©ãŒã å ¥åã API ãªã¯ãšã¹ããªã©ã«å¯ŸããŠåŒ·åºãªããªããŒã·ã§ã³ãå®è£ ããå ¥åããŒã¿ã®å®å šæ§ãæŽåæ§ã確ä¿ããããšãã§ããŸãã