Saat pustaka untuk validasi data quartet
dibuat, landmark berikut ini ditetapkan:
Pada artikel ini, saya ingin mempertimbangkan fokus quartet
pada TypeScript.
Motivasi
Kami mengerjakan proyek kami menggunakan TypeScript. Oleh karena itu, ketika saya membuat perpustakaan ini, saya ingin orang yang tahu TypeScript tidak belajar kuartet sebagai sesuatu yang sama sekali baru baginya, tetapi untuk belajar di perpustakaan ini apa yang sudah dia ketahui.
Pelindung Tipe Yang Ditentukan Pengguna
Pertimbangkan sebuah contoh. Kami meminta data tentang pengguna dengan API. Kami berasumsi bahwa mereka adalah dari jenis berikut:
interface User {
id: string;
name: string;
gender: "male" | "female";
age: number;
phoneBook: {
[name: string]: string;
};
}
Yang ingin saya dapatkan dari fungsi validasi:
const probablyUser: unkown = { ... }
if (checkUser(probablyUser)) {
console.log(probablyUser.name)
} else {
throw new Error('Probably User has not type User')
}
Untuk mencapai tujuan ini, Penjaga Tipe Buatan Pengguna digunakan .
Artinya, deklarasi fungsi akan terlihat seperti ini:
function checkUser(probablyUser: any): probablyUser is User {
}
Mari kita gunakan quartet
untuk membuat fungsi seperti itu:
import { v } from "quartet";
const checkUser = v({
id: v.string,
name: v.string,
gender: ["male", "female"],
age: v.number
phoneBook: {
[v.rest]: v.string,
}
});
Setelah menulis kode seperti itu, kita mendapatkan fungsi yang bukan TypeGuard:
chechUser: (value: any) => boolean;
Untuk membuatnya TypeGuard perlu menunjukkan secara deklaratif jenis mana yang akan divalidasi oleh fungsi ini. Ini dilakukan seperti ini:
const checkUser = v<User>({
});
Akhirnya:
chechUser: (value: any) => value is User
Ada dua poin mengenai item ini:
Jaminan
Fakta bahwa pengembang dapat menunjukkan tipe mana yang divalidasi oleh rangkaian dapat mengingatkan, karena sangat mungkin untuk menulis seperti ini:
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 . — .