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
기반 검증 - 네이티브
JSON
API와 유사한 인터페이스 제공
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 스펙 구현체를 마무리하고
백엔드 프레임워크를 작성해보고 싶네요.
현재 구직중이니 많은 관심 부탁드립니다.
읽어주셔서 감사합니다.
행복한 하루 되세요!