Quatuor 9: Allegro | Manuscrit

Lorsque la bibliothèque de validation des données a quartetété créée, les repères suivants ont été définis:



Dans cet article, je voudrais envisager de me concentrer quartetsur TypeScript.


Motivation


Nous travaillons sur nos projets en utilisant TypeScript. Par conséquent, lorsque j'ai créé cette bibliothèque, je voulais que la personne qui connaît TypeScript n'apprenne pas le quatuor comme quelque chose de complètement nouveau pour lui, mais reconnaisse dans cette bibliothèque ce qu'il sait déjà.


Protecteurs de type définis par l'utilisateur


Prenons un exemple. Nous demandons des données sur l'utilisateur avec l'API. Nous supposons qu'ils sont du type suivant:


interface User {
  id: string;
  name: string;
  gender: "male" | "female";
  age: number;
  phoneBook: {
    [name: string]: string;
  };
}

Ce que je veux obtenir de la fonction de validation:


const probablyUser: unkown = { ... }

if (checkUser(probablyUser)) {
    // probablyUser has type User
    console.log(probablyUser.name)
} else {
    // probablyUser has type unkown
    throw new Error('Probably User has not type User')
}

Pour atteindre cet objectif, des protections de type définies par l'utilisateur sont utilisées .


Autrement dit, la déclaration de fonction devrait ressembler à ceci:


function checkUser(probablyUser: any): probablyUser is User {
  // ...
}

Utilisons quartetpour créer une telle fonction:


import { v } from "quartet";

const checkUser = v({
  id: v.string,
  name: v.string,
  gender: ["male", "female"],
  age: v.number
  phoneBook: {
    [v.rest]: v.string,
  }
});

Après avoir écrit un tel code, nous obtenons une fonction qui n'est pas TypeGuard:


chechUser: (value: any) => boolean;

Pour le rendre TypeGuard, il est nécessaire d'indiquer de manière déclarative quel type sera validé par cette fonction. Cela se fait comme ceci:


const checkUser = v<User>({
  // ...
});

Finalement:


chechUser: (value: any) => value is User

Il y a deux points concernant cet article:


garantie


Le fait même que le développeur puisse indiquer quel type est validé par le circuit peut alerter, car il est tout à fait possible d'écrire comme ceci:


const checkNumber = v<number>({ name: v.string });
// checkNumber: (value: any) => value is number

{ 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)) {
  // value has type never
}

, , .


, 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,
  }
})

image


- : 24


hapi/joi


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())
});

image


, , 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"
      }
    }
  }
});

image


, 146 .


:


image


TypeScript. , , , .



TypeGuard — , .


TypeScript . — .


All Articles