рдЬрдм рдбреЗрдЯрд╛ рд╕рддреНрдпрд╛рдкрди рдХреЗ рд▓рд┐рдП рдкреБрд╕реНрддрдХрд╛рд▓рдп quartet
рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛, рддреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕реНрдерд▓ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдП рдЧрдП рдереЗ:
рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ quartet
рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░рдиреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ред
рдкреНрд░реЗрд░рдгрд╛
рд╣рдо рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдкрдиреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдкрд░ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рдЬрдм рдореИрдВрдиреЗ рдЗрд╕ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд┐рдпрд╛, рддреЛ рдореИрдВ рдЪрд╛рд╣рддрд╛ рдерд╛ рдХрд┐ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЬрд╛рдирдиреЗ рд╡рд╛рд▓рд╛ рд╡реНрдпрдХреНрддрд┐ рдЪреМрдХрдбрд╝реА рди рд╕реАрдЦреЗ, рдХреНрдпреЛрдВрдХрд┐ рдЙрд╕рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдирдпрд╛ рд╣реЛ, рд▓реЗрдХрд┐рди рдЗрд╕ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рдкрд╣рдЪрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рд╡рд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХреНрдпрд╛ рдЬрд╛рдирддрд╛ рд╣реИред
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛-рдкрд░рд┐рднрд╛рд╖рд┐рдд рдкреНрд░рдХрд╛рд░ рдХреЗ рдЧрд╛рд░реНрдб
рдПрдХ рдЙрджрд╛рд╣рд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рд╣рдо рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдбреЗрдЯрд╛ рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдорд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рд╡реЗ рдирд┐рдореНрди рдкреНрд░рдХрд╛рд░ рдХреЗ рд╣реИрдВ:
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,
}
});
рдЗрд╕ рддрд░рд╣ рдХреЗ рдХреЛрдб рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдорд┐рд▓рддрд╛ рд╣реИ рдЬреЛ рдЯрд╛рдЗрдкрдЧрд╛рд░реНрдб рдирд╣реАрдВ рд╣реИ:
chechUser: (value: any) => boolean;
рдЯрд╛рдЗрдкрдЧрд╛рд░реНрдб рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣ рдШреЛрд╖рд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдХрд┐ рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рджреНрд╡рд╛рд░рд╛ рдХрд┐рд╕ рдкреНрд░рдХрд╛рд░ рдХреЛ рдорд╛рдиреНрдп рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдпрд╣ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
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 . тАФ .