valdex - ไลบรารี assertion ประเภทรันไทม์สำหรับ Typescript ที่ใช้งานง่าย
(github.com/asheswook)สวัสดีครับ
โดยทั่วไปแล้ว หากพัฒนาแบ็กเอนด์ด้วย Typescript จุดที่มักเกิดข้อผิดพลาดบ่อยคือส่วนของ รันไทม์ ที่ไม่สามารถตรวจจับได้ในช่วงคอมไพล์ไทม์
ยกตัวอย่างเช่น implementation ของ repository ที่ใช้แปลง DB row หรือ ส่วนที่สื่อสารกับ API ภายนอก ซึ่งเป็นจุดที่เกิดบ่อยที่สุด
เช่น ค่าที่รับมาจาก DB อาจต่างจากที่คาดไว้ ทำให้มีการใส่ค่า undefined เข้าไปในรันไทม์ หรือในตอนทำ casting ก็อาจตีความค่าพื้นฐานที่มาจากภายนอกผิดพลาดจนเกิด human error ได้
แม้แต่ตอน implement repository ก็ต้องคอยเขียน type สำหรับค่าพื้นฐานที่มาจากภายนอกด้วย interface แบบแปะเพิ่มไปเรื่อย ๆ แม้อาจเป็นปัญหาเล็กน้อย แต่ผมเลยทำตัวนี้ขึ้นมาเพื่อให้ใช้งานได้สะดวกขึ้น
ในการใช้งานจริง ทั้งโค้ดส่วน API ภายนอกและ implementation ของ DB กระชับขึ้นมาก และ ข้อผิดพลาดที่เกิดในรันไทม์ก็ลดลงด้วย
หลังจากทีมลองใช้กับแบ็กเอนด์แล้วรู้สึกว่าใช้ได้ดี จึงนำขึ้นเผยแพร่บน npm
import { validate } from 'valdex';
const data: unknown = await fetchData();
validate(data, {
name: String,
age: Number,
active: Boolean
});
// TypeScript now knows the exact type of data
data.name // string
data.age // number
data.active // boolean
ตัวอย่างข้างต้นสมมติสถานการณ์ที่ดึงข้อมูลมาจากภายนอก ไม่ว่าจะใช้ axios, mysql2 หรือ postgres pg ก็สามารถนำไปใช้ได้ โดยจะทำการตรวจสอบค่าที่เข้ามาในรูปแบบ unknown และหากถูกต้อง ใน control flow หลังจากนั้นค่านั้นจะถูก assertion (asserts) ให้เป็นค่าตามที่กำหนดไว้ใน validate()
แน่นอนว่าคุณอาจเลือกใช้ไลบรารีอย่าง zod ก็ได้
แต่สิ่งที่แตกต่างกันระหว่าง zod กับ valdex คือ valdex ไม่ได้สร้าง schema เป็น instance เพื่อใช้งาน แต่สามารถจัดการประเภทข้อมูลแบบ declarative ได้ภายในจุดที่รับข้อมูลมาเลย จึงไม่จำเป็นต้องคอยเลื่อนขึ้นลงไปแก้ interface หรือแก้คลาส DTO เพื่อปรับโค้ดอีกต่อไป
npm i valdex
สามารถติดตั้งผ่าน npm แล้วลองใช้งานได้
2 ความคิดเห็น
ถ้าเป็นแค่ประเภทข้อมูลแบบง่าย ๆ ก็น่าจะให้ DX ที่ดีมากเลยล่ะ โอ้โห
รองรับทั้ง Nested Object และ Array เลยทำให้จนถึงตอนนี้ยังไม่มีส่วนไหนที่ติดขัดน่ารำคาญเวลาใช้งานกับ API ภายนอกหรือทำ implementation ของรีโพซิทอรีครับ
ขอบคุณที่ให้ความสนใจครับ!