Show GN: TypeScript 기반 JSON Schema 구현과 개발 도구 모음
(github.com/imhonglu)"내 취향의 타입 안전한 라이브러리를 만들어보자"는 마음으로 시작한 프로젝트입니다.
이 프로젝트는 타입 안전한 JSON Schema 구현체를 시작으로 개발 과정에서 필요한 다양한 도구들로 자연스럽게 확장되었습니다.
현재 구직을 위해 1차적으로 마침표를 찍어보았습니다.
프로젝트 원칙
다음과 같은 핵심 원칙을 준수하며 개발되었습니다:
- 엄격한 타입 시스템 활용
 - 최소한의 외부 의존성 유지
 - 재사용 가능한 타입 시스템 설계
 - API 문서화
 - 높은 테스트 커버리지 유지
 - 순수 타입스크립트 구현
 
라이브러리
@imhonglu/json-schema
JSON Schema 2020-12 draft 사양을 준수하는 TypeScript 구현체입니다.
- 저장소: https://github.com/imhonglu/new-wheels/…
 - 
JSON-Schema-Test-Suite를 통한 검증 - 스키마 정의에 따라 사용 가능한 키워드의 타입이 자동으로 추론됩니다.
 
import { Schema, SchemaDefinition } from "@imhonglu/json-schema";  
  
export const Address = new Schema({  
  type: "object",  
  properties: {  
    street: { type: "string" },  
    city: { type: "string" },  
    zip: { type: "string" },  
  },  
  required: ["street"] as const,  
});  
  
export type Address = SchemaDefinition.Instance<typeof Address>;  
// {  
//   street: string;  
//   city?: string;  
//   zip?: string;  
// }  
@imhonglu/format
JSON Schema의 format 키워드를 구현하기 위해 시작된 프로젝트입니다.
- 저장소: https://github.com/imhonglu/new-wheels/…
 - RFC 사양 기반 구현
 - 
JSON-Schema-Test-Suite기반 검증 - 네이티브 
JSONAPI와 유사한 인터페이스 제공 
import { FullTime } from '@imhonglu/format';  
  
const time = FullTime.parse('00:00:00.000Z');  
// { hour: 0, minute: 0, second: 0, secfrac: '.000', offset: undefined }  
  
console.log(time.toString()); // '00:00:00.000Z'  
console.log(JSON.stringify(time)); // '"00:00:00.000Z"'  
  
const result = FullTime.safeParse('invalid');  
if (!result.ok) {  
  console.error(result.error);  
}  
@imhonglu/pattern-builder
RFC 스펙의 ABNF 문법 구현중 정규식의 가독성 향상을 위해 만들어진 regex 빌더입니다.
import { characterSet, concat, hexDigit } from "@imhonglu/pattern-builder";  
  
// pct-encoded = "%" HEXDIG HEXDIG  
export const pctEncoded = concat(  
  "%",  
  hexDigit.clone().exact(2),  
);  
  
// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"  
export const unreserved = characterSet(  
  alpha,  
  digit,  
  /[\-._~]/,  
);  
@imhonglu/type-guard
타입 가드의 가독성 향상을 위해 만들어진 타입 가드 라이브러리입니다.
- 저장소: https://github.com/imhonglu/new-wheels/…
 - Proxy 기반의 구현으로 오버헤드 최소화
 - 
not키워드 제공 
import { composeGuards } from "@imhonglu/type-guard";  
  
const is = composeGuards({  
  string: (value: unknown): value is string => typeof value === "string",  
  number: (value: unknown): value is number => typeof value === "number"  
});  
  
is.string("hello"); // true  
is.not.string(42);  // true  
  
let value: string | number | undefined;  
  
if (is.number(value)) {  
  value.toFixed(2); // 'value' is number  
}  
  
if (is.not.number(value)) {  
  value.toFixed(2); // error: Property 'toFixed' does not exist on type 'undefined'.  
}  
@imhonglu/type-object
네이티브 Object API의 타입 안전한 래퍼 라이브러리입니다. 네이티브 동작에 가까운 타입을 제공합니다.
import * as TypeObject from '@imhonglu/type-object';  
  
const data = { a: 1, b: 2, c: 3 };  
for (const key of TypeObject.keys(data)) {  
  // key: "a" | "b" | "c"  
  console.log(data[key]); // number  
}  
  
const string = 'hello';  
for (const index of TypeObject.keys(string)) {  
  // index: number & keyof string  
  console.log(string[index]); // string  
}  
@imhonglu/toolkit
프로젝트 내부에서 사용중인 유틸리티 타입과 유틸리티 함수들의 모음입니다.
import type { Fn } from '@imhonglu/toolkit';  
  
// 함수 타입 '(...args: any[]) => any' 에 대한 타입 별칭을 제공합니다.  
Fn.Callable // (...args: any[]) => any  
  
// 제네릭을 통해 인자 유형만 정의할 수 있습니다.  
Fn.Callable<{ args: [number, number] }> // (...args: [number, number]) => any  
  
// 제네릭을 통해 반환 유형만 정의할 수 있습니다.  
Fn.Callable<{ return: string }> // (...args: any[]) => string  
  
// 제네릭을 통해 인자 유형과 반환 유형을 모두 정의할 수 있습니다.  
Fn.Callable<{ args: [number, number], return: string }> // (...args: [number, number]) => string  
향후 계획 및 구직
진행 중인 프로젝트의 다음 단계는 JSON Schema 스펙 구현체를 마무리하고
백엔드 프레임워크를 작성해보고 싶네요.
현재 구직중이니 많은 관심 부탁드립니다.
읽어주셔서 감사합니다.
행복한 하루 되세요!