TLDR : 검증과 객체 생성을 동시해 해주며 타입스크립트 타입도 만들어 주는 라이브러리를 사용하자
![](https://blog.kakaocdn.net/dn/HDSnX/btrPDfg7Rt6/eAQoJuvt88pOlgE6APzEK1/img.jpg)
검증 예시
import * as yup from "yup";
let schema = yup.object().shape({
name: yup.string().required(),
age: yup.number().required().positive().integer(),
email: yup.string().email(),
website: yup.string().url(),
createdOn: yup.date().default(function () {
return new Date();
}),
});
// data from an API, from user, etc. Note that the type would be `any`
// (or perhaps `unkown`) as we don't really know what it looks like
// if it comes from outside
const data: any = {
name: 'jimmy',
age: 24,
}
// check validity
schema
.isValid(data)
.then(function (valid) {
console.log('isValid?', valid); // => true
// do something with the data, however, it's still `any`/`unkown`....
});
let userSchema = yup.object().shape({
name: yup.string().required(),
age: yup.number().required().positive().integer(),
email: yup.string().email(),
website: yup.string().url(),
createdOn: yup.date().default(function () {
return new Date();
}),
});
type UserType = {
name: string
age: number
email: string
website: string
createdOn: Date,
}
// check validity
schema
.isValid(data)
.then(function (valid) {
const user = data as UserType // it's valid so let's cast!
});
function parseUserData(data: any): UserType | Error.
그래서 파싱이 뭔가요?
> Parsing, syntax analysis, or syntactic analysis is the process of analyzing a string of symbols, either in natural language, computer languages or data structures, conforming to the rules of a formal grammar.
[https://en.wikipedia.org/wiki/Parsing]
어렵게 파싱 하기
주 : 파서와 생성자를 통합함.
// Let's use some custom type aliases for readability
type PositiveInteger = number
type Email = string
type URL = string
// Type guards to validate invidiual values, fields
const isPositiveInteger = (x: any): x is PositiveInteger =>
yup.number().required().positive().integer().isType(x)
const isEmail = (x: any): x is Email =>
yup.string().required().email().isType(x)
const isURL = (x: any): x is URL => yup.string().required().url().isType(x)
const isDate = (x: any): x is Date => yup.date().required().isType(x)
const isString = (x: any): x is string => yup.string().required().isType(x)
// UserType again, now with our custom type aliases
type UserType = {
name: string
age: PositiveInteger
email?: Email
website?: URL
createdOn?: Date
}
/**
parse, don't validate
compiler can help us quite a bit here to make sure the parsing
is actually correct
*/
const parseToUserType = (x: any): UserType | Error => {
let { name, age, email, website, createdOn } = x
if (!isString(name)) return new Error("invalid name")
if (!isPositiveInteger(age)) return new Error("invalid age")
email = isEmail(email) ? email : undefined // optional, silently drop invalid values
website = isURL(website) ? website : undefined // optional, silently drop invalid values
createdOn = isDate(createdOn) ? createdOn : new Date() // optional, use default if invalid
return { age, name, createdOn, email, website }
}
// Business logic is pretty awesome now!
function myHandler(): Response {
const userType: UserType | Error = parseToUserType(data)
if (userType instanceof Error) return { error: "Ohh there was a 400 error" }
// use UserType normally, do what ever you want
return { message: `Welcome, ${userType.name}` }
}
이제 비즈니스 로직에서 모든 데이터를 UserType으로 파싱할 수 있습니다.
- 오류가 있는지 없는지 확인하고 문제가 없는지 확인합니다.
우리는 문자열이나 숫자보다 더 정확한 타입을 사용하고 있습니다.
- 타입 별칭이 작동하는 방식으로 인해 타입 가드가 더 화려하더라도 이메일 유형은 여전히 문자열일 뿐입니다. 이에 대해서는 나중에 다시 살펴보겠습니다.
오류가 발생하기 쉽고 위험하며 타입 검사가 잘 되지 않는 코드는 타입 가드로 제한됩니다.
- 그것들을 잘 테스트하고 특정 유형에 대한 파서를 작성하는 것은 쉽습니다 :)
TS 컴파일러는 파서가 실제로 작동하는지 확인합니다.
- 우리는 안전하게 our(x: any) => UserType | Error 파서 함수에서 잘 지원되는 오류 파서 기능입니다.
파서와 타입 가드를 작성하는 것은 여전히 힘이 많이 듭니다.
- 그들은 또한 매우 상용구처럼 보입니다. 분명히 미리 빌드된 타입 가드가 있는 일부 라이브러리와 파서를 구축하는 도구가 있겠죠?
깨달음을 얻은 것처럼 파싱
import * as RT from "runtypes"
/*
TS does not support accessing types during runtime, so instead,
we let Runtypes create the type for us using their own Domain
Specific Language (DSL) to declare the schema & type at the
same time.
*/
const UserType = RT.Record({
name: RT.String,
age: RT.Number.withBrand("PositiveInteger").withConstraint((n) => n > 0),
email: RT.String.withBrand("Email").withConstraint(isEmail).optional(),
website: RT.String.withBrand("URL").withConstraint(isURL).optional(),
createdOn: RT.InstanceOf(Date).optional(),
})
// if you want to get the TS type, eg. for function signatures
type UserType = RT.Static<typeof UserType>
declare const data: any // (just so this example compiles)
try {
// "If the object doesn't conform to the type specification, check will throw an exception."
const userType: UserType = UserType.check(data)
console.log(`The User ${userType.name} has arrived!`)
} catch (error) {
console.error(`Oof, data wasn't what we want! ${error}`)
- 구문 분석이 정말 쉽고 간결해집니다.
- 거의 우아한 Runtypes는 JS 객체용 파서를 생성하기 위한 기본 도구 상자를 제공합니다.
- 타입 == 스키마 == 파서
- 3개를 따로 관리할 필요가 없습니다. Runtypes 객체는 타입, 스키마 및 파서를 하나로 통합한 것입니다!
- 우리는 여전히 일부 타입 가드(withConstraint)를 사용하고 있습니다
- Runtypes은 매우 기본적인 타입과 함께 제공되므로 여기에서 사용할 수 있는 중요하고 유용한 유효성 검사 논리가 여전히 포함되어 있습니다.
- 타입 가드는 TypeScript에서 "유효성을 검사 대신 파싱하는" 라이브러리를 지원하는 언어 기능입니다.
- .check에서 오류가 발생하므로 이를 catch 하는 것을 잊지 마세요!
- UserType 대신에 Error가 발생했지만 우리는 이미 여기에서 꽤 좋은 위치에 있습니다. 그러나 Zod 및 Funtypes(Runtypes 포크)는 이 문제를 해결합니다.
결론
지금까지 배운 내용에 만족하신다면 지금이 바로 박수 및 팔로우를 누르고 Runtypes 또는 Zod를 실행해 볼 수 있는 좋은 시간입니다!
그러나 아래의 보너스 섹션을 반드시 확인해야한다고 생각합니다!
주 : 원문은 원래 다른 라이브러리들도 다루고 있지만,
현재 대세는 zod로 굳어진 상황이기에 번역하여 정리하지 않았습니다.
참고 :
https://github.com/colinhacks/zod#brand
GitHub - colinhacks/zod: TypeScript-first schema validation with static type inference
TypeScript-first schema validation with static type inference - GitHub - colinhacks/zod: TypeScript-first schema validation with static type inference
github.com
https://www.totaltypescript.com/tutorials/zod
Zod Tutorial
Zod is a TypeScript-first schema declaration and validation library. In this tutorial, Matt Pocock has prepared a set of exercises that will help you level up.
www.totaltypescript.com
'FrontEnd' 카테고리의 다른 글
개발자 관점에서 Next13 간단히 살펴보기 (6) | 2022.10.28 |
---|---|
[프론트엔드 인터뷰 퀴즈] 정적 클래스 멤버(프로퍼티 / 메서드)를 사용하는 이유는 뭘까요? (0) | 2022.10.28 |
완벽하게 타입 안전한 웹 애플리케이션 개발[Fully Typed Web Apps] (0) | 2022.10.26 |
Iframe 완벽 가이드 (0) | 2022.10.26 |
[1일 1 알고리즘] 프론트엔드 JS 알고리즘 문제풀이 : 배열 평탄화(flatten) (0) | 2022.10.25 |