عندما quartet
تم إنشاء مكتبة للتحقق من صحة البيانات ، تم تعيين المعالم التالية:
في هذه المقالة ، أود التفكير في التركيز quartet
على TypeScript.
التحفيز
نحن نعمل على مشاريعنا باستخدام TypeScript. لذلك ، عندما أنشأت هذه المكتبة ، أردت من الشخص الذي يعرف TypeScript ألا يتعلم الرباعية كشيء جديد تمامًا بالنسبة له ، ولكن أن يتعرف في هذه المكتبة على ما يعرفه بالفعل.
حراس النوع المعرفة من قبل المستخدم
تأمل في مثال. نطلب بيانات حول المستخدم مع واجهة برمجة التطبيقات. نفترض أنها من النوع التالي:
interface User {
id: string;
name: string;
gender: "male" | "female";
age: number;
phoneBook: {
[name: string]: string;
};
}
ما أريد الحصول عليه من وظيفة التحقق من الصحة:
const probablyUser: unkown = { ... }
if (checkUser(probablyUser)) {
console.log(probablyUser.name)
} else {
throw new Error('Probably User has not type User')
}
لتحقيق هذا الهدف ، يتم استخدام حراس النوع المعرفة من قبل المستخدم .
أي ، يجب أن يظهر إعلان الوظيفة على النحو التالي:
function checkUser(probablyUser: any): probablyUser is User {
}
دعونا نستخدم quartet
لإنشاء مثل هذه الوظيفة:
import { v } from "quartet";
const checkUser = v({
id: v.string,
name: v.string,
gender: ["male", "female"],
age: v.number
phoneBook: {
[v.rest]: v.string,
}
});
بعد كتابة هذا الرمز ، نحصل على وظيفة ليست TypeGuard:
chechUser: (value: any) => boolean;
لجعله TypeGuard ، من الضروري الإشارة بشكل واضح إلى النوع الذي سيتم التحقق منه بواسطة هذه الوظيفة. يتم ذلك على النحو التالي:
const checkUser = v<User>({
});
في النهاية:
chechUser: (value: any) => value is User
هناك نقطتان بخصوص هذا البند:
ضمان
إن حقيقة أن المطور يمكن أن يشير إلى النوع الذي تم التحقق من صحته بواسطة الدائرة يمكن أن ينبه ، لأنه من الممكن جدًا الكتابة مثل هذا:
const checkNumber = v<number>({ name: v.string });
— { name: string }
, , number
.
. ( ) , — "" .
, .
, v
. :
const v: <T>(schema: Schema) => (value: any) => value is T;
.
, TypeGuard .
:
const v: <T = any>(schema: Schema) => (value: any) => value is T;
, — never
:
const checkNumber = v(v.number);
const value: any = "123";
if (!checkNumber(value)) {
}
,
,
.
, T
any
, T === any
, .
- :
const v: <T = any>(
schema: Schema
) => IfAny<T, (value: any) => boolean, (value: any) => value is T>;
type IfAny<T,A,B> =
— , :
T — any
:
type IfAny<T, A, B> = true extends T
? "1" extends T
? 1 extends T
? {} extends T
? (() => void) extends T
? null extends T
? A
: B
: B
: B
: B
: B
: B;
, , : boolean | number | string | object | function | null
any
.
TypeScript
, , TypeScript'a .
@hapi/joi
ajv
, User
.
Text Compare .
quartet
const checkUser = v({
id: v.string,
name: v.string,
gender: ["male", "female"],
age: v.number
phoneBook: {
[v.rest]: v.string,
}
})

- : 24
const schema = j.object({
id: j.string().required(),
name: j.string().required(),
gender: j
.string()
.valid("male", "female")
.required(),
age: j.number().required(),
phoneBook: j.object().pattern(/.*/, j.string())
});

, , 118 .
ajv
const checkUser = a.compile({
type: "object",
required: ["id", "name", "gender", "age", "phoneBook"],
properties: {
id: { type: "string" },
name: { type: "string" },
gender: { type: "string", enum: ["male", "female"] },
phoneBook: {
type: "object",
additionalProperties: {
type: "string"
}
}
}
});

, 146 .
:

TypeScript. , , , .
TypeGuard — , .
TypeScript . — .