6 điểm bởi honglu 2025-01-08 | 2 bình luận | Chia sẻ qua WhatsApp

Đây là một dự án được bắt đầu với mong muốn “hãy tự tạo ra một thư viện an toàn kiểu đúng gu của mình”.

Dự án này khởi đầu từ một bộ triển khai JSON Schema an toàn kiểu và sau đó tự nhiên mở rộng thành nhiều công cụ khác nhau cần thiết trong quá trình phát triển.

Hiện tại, tôi tạm khép lại giai đoạn đầu tiên để chuẩn bị cho việc tìm việc.

Nguyên tắc dự án

Dự án được phát triển với việc tuân thủ các nguyên tắc cốt lõi sau:

  • Tận dụng hệ thống kiểu nghiêm ngặt
  • Duy trì tối thiểu các phụ thuộc bên ngoài
  • Thiết kế hệ thống kiểu có thể tái sử dụng
  • Tài liệu hóa API
  • Duy trì độ bao phủ kiểm thử cao
  • Triển khai hoàn toàn bằng TypeScript thuần

Thư viện

@imhonglu/json-schema

Đây là bộ triển khai TypeScript tuân thủ đặc tả JSON Schema draft 2020-12.

  • Kho mã: https://github.com/imhonglu/new-wheels/…
  • Được kiểm chứng thông qua JSON-Schema-Test-Suite
  • Kiểu của các keyword có thể dùng sẽ được tự động suy luận theo định nghĩa schema.

[IMG] demo-1

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

Đây là dự án được bắt đầu để triển khai keyword format của JSON Schema.

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

Đây là regex builder được tạo ra để cải thiện khả năng đọc của biểu thức chính quy trong quá trình triển khai ngữ pháp ABNF của đặc tả RFC.

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

Đây là thư viện type guard được tạo ra để cải thiện tính dễ đọc của type guard.

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

Đây là thư viện wrapper an toàn kiểu cho Object API gốc. Nó cung cấp các kiểu gần với hành vi gốc.

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

Đây là tập hợp các utility type và utility function đang được sử dụng bên trong dự án.

import type { Fn } from '@imhonglu/toolkit';  
  
// Cung cấp type alias cho kiểu hàm '(...args: any[]) => any'.  
Fn.Callable // (...args: any[]) => any  
  
// Có thể chỉ định riêng kiểu tham số thông qua generic.  
Fn.Callable<{ args: [number, number] }> // (...args: [number, number]) => any  
  
// Có thể chỉ định riêng kiểu trả về thông qua generic.  
Fn.Callable<{ return: string }> // (...args: any[]) => string  
  
// Có thể đồng thời chỉ định cả kiểu tham số và kiểu trả về thông qua generic.  
Fn.Callable<{ args: [number, number], return: string }> // (...args: [number, number]) => string  

Kế hoạch sắp tới và tìm việc

Bước tiếp theo của dự án đang thực hiện là hoàn thiện bộ triển khai đặc tả JSON Schema
và tôi cũng muốn thử viết một backend framework.

Hiện tôi đang tìm việc, rất mong nhận được sự quan tâm từ mọi người.
Xin cảm ơn vì đã đọc.

Chúc bạn một ngày vui vẻ!

2 bình luận

 
jjpark78 2025-01-09

Bên này có một lựa chọn rất nổi bật là zod nên trong sản phẩm chúng tôi đang dùng cái đó, nhưng cũng khá thú vị đấy

 
honglu 2025-01-09

Các dự án có sẵn như ajv, typia, zod cũng là những dự án mà tôi đang theo dõi với sự quan tâm lớn.

Trường hợp safeParse của @imhonglu/format cũng là một tính năng chịu ảnh hưởng từ API của zod.

Cảm ơn bạn đã quan tâm!