19 août 2023

github repository: ts-codebase

Intro typescript

index.html

<!DOCTYPE html>
<html lang="fr">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
</head>

<body>
    Intro typescript
    <script src="01_types.js"></script>
    <script src="02_data_structure.js"></script>
    <script src="03_enums_tuples.js"></script>
</body>

</html>

Les types en typescript

01_types.ts

/**
 * Les types en typescript
 */

//quand le type n'est pas defini des le debut,
// alors il est réassignable
// c'est le type Any qui est attribué par défaut
let my_var;
my_var = "username";
console.assert(my_var === "username");
my_var = 11;
console.assert(my_var === 11);
my_var = true;
console.assert(my_var === true);

let age = 1;
console.assert(age === 1);
age = 2;
// age="trois" c'est impossible
// car l'inference de type a attribué le type number
console.assert(age === 2);

// Déclaration explicite de type
let pi: Number = 3.14;
console.assert(typeof pi === "number");

Fonctions

Les fonctions sont des blocs de code réutilisables.

Exemple de cote :

const add = (a: number, b: number): number => a + b;

Structure de données

02_data_structure.ts

/***
 * Structure de données:
 * Avec le type any on peut changer
 * le type de la variable à tout instruction
 * Lorsque l'on fixe le type
 * alors il n'est plus possible de le changer
 * lors d'une assignation
 */

// Arrays
let buddies: any[] = [
    "cheroliv",
    "imrandeh",
    "issoudeh",
    "soumi92"
]

console.assert(buddies[0] === "cheroliv");
console.assert(buddies[1] === "imrandeh");
console.assert(buddies[2] === "issoudeh");
console.assert(buddies[3] === "soumi92");
// Déclaré en type any, l'inference de type
// a bien réaligné en type string
console.assert(typeof buddies[0] === "string");
console.assert(typeof buddies[1] === "string");
console.assert(typeof buddies[2] === "string");
console.assert(typeof buddies[3] === "string");



let writers: (String | String | String | Number)[][] = [
    ["Chrétien", "de Troyes", "fr", 12],
    ["François", "Rabelais", "fr", 16],
    ["René", "Descartes", "fr", 17],
    ["Jean-Jacques", "Rousseau", "fr", 18],
    ["Georg", "Hegel", "de", 19],
    ["Karl", "Marx", "de", 19],
    ["Friedrich", "Engels", "de", 19],
    ["Victor", "Hugo", "fr", 19],
    ["Paul", "Verlaine", "fr", 19],
    ["Arthur", "Rimbaud", "fr", 19],
    ["Gérard", "de Nerval", "fr", 19],
    ["Georg", "Lukacs", "hu", 20],
    ["Franz", "Kafka", "hu", 20],
    ["Antonio", "Gramsci", "it", 20],
    ["Domenico","Losurdo","it",20],
];

// console.table(writers);


// Objects
let author: {
    first_name: String,
    last_name: String,
    lang: String,
    century: Number
} = {
    // slice(-1) renvoie le dernier élèment
    first_name: writers.slice(-1)[0][0] as String,
    last_name: writers.slice(-1)[0][1] as String,
    lang: writers.slice(-1)[0][2] as String,
    century: writers.slice(-1)[0][3] as Number,
}


// assertion sur la valeur en accés par encapsulation(dot)
console.assert(author.first_name === "Antonio")
console.assert(author.last_name === "Gramsci")
console.assert(author.lang === "it")
console.assert(author.century === 20);

// assertion sur le type en accès par index
console.assert(typeof author["first_name"] === "string")
console.assert(typeof author["last_name"] === "string")
console.assert(typeof author["lang"] === "string")
console.assert(typeof author["century"] === "number");

Enums et tuples

03_enums_tuples.ts

/**
 * Enums et Tuples
 *
 * Enum: il existe les enums numérique
 * et les enums chaine de caracteres.
 *
 * Tuple: similaire aux arrays mais ne peut
 * contenir qu'une valeur de type spécifié.
 *
 */

//Enum numérique
// l'index par de debut défaut est 0
// ici on le place a 1
enum Week {
    Monday = 1,
    Tuesday = 2,
    Wednesday = 3,
    Thursday = 4,
    Friday = 5,
    Saturday = 6,
    Sunday = 7,
};

console.assert(Week.Monday == 1);
console.assert(Week.Tuesday == 2);
console.assert(Week.Wednesday == 3);
console.assert(Week.Thursday == 4);
console.assert(Week.Friday == 5);
console.assert(Week.Saturday == 6);
console.assert(Week.Sunday == 7);

console.assert(Week[1] === "Monday");
console.assert(Week[2] === "Tuesday");
console.assert(Week[3] === "Wednesday");
console.assert(Week[4] === "Thursday");
console.assert(Week[5] === "Friday");
console.assert(Week[6] === "Saturday");
console.assert(Week[7] === "Sunday");

let motd_arr_fr: String[] = [
    "Associé à la Lune",
    "Du dieu Tiw, associé à Mars",
    "Du dieu germanique Odin",
    "Du dieu germanique du tonnerre Thor",
    "De la déesse germanique Frigga associée à Vénus",
    "Associé à Saturne",
    "Associé au Soleil",
];

let motd_arr_en: String[] = [
    "associated with the Moon",
    "from the god Tiw, associated with Mars",
    "from Germanic god Odin",
    "from Germanic god of thunder Thor",
    "from Germanic goddess Frigga associated with Venus",
    "associated with Saturn",
    "associated with the Sun",
];

// Un tuple (triple)
let monday_triple_fr: [
    Number,
    String,
    String
] = [
        Week.Monday,
        Week[Week.Monday],
        motd_arr_fr[0],
    ];


console.assert(monday_triple_fr[0] === 1);
console.assert(monday_triple_fr[1] === "Monday");
console.assert(monday_triple_fr[2] === "Associé à la Lune");


let monday_triple_en: [
    Number,
    String,
    String
] = [
        Week.Monday,
        Week[Week.Monday],
        motd_arr_en[0],
    ];

console.assert(monday_triple_en[0] === 1);
console.assert(monday_triple_en[1] === "Monday");
console.assert(monday_triple_en[2] === "associated with the Moon");


// On se fait un type pour ajouter le nom de la langue
type Meaning_of_the_day = {
    lang: String,
    meaning: (Week | String)[][],
};

//fonction d'affichage du type Meaning_of_the_day
const display_motd = (motd: Meaning_of_the_day) => {
    motd.meaning.forEach(day =>
        console.table(`${Week[day[0] as Week]}: ${day[1]}.(${motd.lang})`)
    )
};

//fonction d'assertion sur le type Meaning_of_the_day
// afin de verifier la concordance du contenu avec
// motd_arr_#lang#
const test_motd = (
    motd: Meaning_of_the_day,
    motd_arr: String[]
) => {
    console.assert(motd.lang.length === 2)
    for (const [i, value] of motd.meaning.entries()) {
        console.assert(value[1] === motd_arr[i]);
    }
};


let motd_fr: Meaning_of_the_day = {
    lang: "fr",
    meaning: [
        [Week.Monday, motd_arr_fr[0]],
        [Week.Tuesday, motd_arr_fr[1]],
        [Week.Wednesday, motd_arr_fr[2]],
        [Week.Thursday, motd_arr_fr[3]],
        [Week.Friday, motd_arr_fr[4]],
        [Week.Saturday, motd_arr_fr[5]],
        [Week.Sunday, motd_arr_fr[6]],
    ],
}

console.log("---------");
console.log("display_motd(motd_fr):");
display_motd(motd_fr);
test_motd(motd_fr, motd_arr_fr)


let motd_en: Meaning_of_the_day = {
    lang: "en",
    meaning: [
        [Week.Monday, motd_arr_en[0]],
        [Week.Tuesday, motd_arr_en[1]],
        [Week.Wednesday, motd_arr_en[2]],
        [Week.Thursday, motd_arr_en[3]],
        [Week.Friday, motd_arr_en[4]],
        [Week.Saturday, motd_arr_en[5]],
        [Week.Sunday, motd_arr_en[6]],
    ],
}

console.log("---------");
console.log("display_motd(motd_en):");
display_motd(motd_en);
console.log("---------");
test_motd(motd_en, motd_arr_en);

// Un tuple (triple) utilisant le type
// Meaning_of_the_day pour peupler le meaning
let motd_triple: [
    Number,
    String,
    String
] = [
        Week.Monday,
        Week[Week.Monday],
        motd_fr.meaning[0][1] as String
    ];

console.assert(motd_triple[0] === 1);
console.assert(motd_triple[1] === "Monday");
console.assert(motd_triple[2] === "Associé à la Lune");

Void et Never

04_void_never_types.ts

// Le type void est l'opposé du type any
// c'est l'absence de type.
function verify_writers_length(): void {
    console.assert(writers.length > 0);
}

verify_writers_length();

const verify_writers_length_arrow = (): void =>
    console.assert(writers.length > 0);

verify_writers_length_arrow();

//Type of et never
let value = 30;
console.assert(typeof value === "number");

//never: qqchs qui n'arrive jamais
function foo(x: String | Number): Boolean {
    if (typeof x === "string") {
        return true;
    } else if (typeof x === "number") {
        return false;
    }
    return fail("Error!")
}

function fail(message: String): never {
    throw new Error(message as string);
}

Classes et interfaces

04_void_never_types.ts

/**
 * Les classes:
 * members,
 * visibility,
 * nommage,
 * accesseurs
 * scope identifier: static,private,protected
 *
 * convention de nommage :
 * Les membres private sont préfixés avec un _ *
 */

class Member {
    username: String = "";
    email: String = "";
    private _password: String = "";
    readonly signup_date: Date = new Date(Date.now());

    constructor(username: String, email: String) {
        this.username = username;
        this.email = email;
    }

    get password(): String {
        return this._password;
    }

    set password(new_password: String) {
        this._password = new_password;
    }

    /**
     * Une fonction static qui initilise un member,
     * à partir d'un author
     */
    static fromAuthor(author: {
        first_name: String,
        last_name: String,
        lang: String,
        century: Number
    }): Member {
        return new Member(
            `${author.first_name}.${author.last_name}`,
            `${author.first_name}.${author.last_name}@acme.com`,
        );
    }
};


let domenico = Member.fromAuthor(author);
domenico.password = "test";

console.assert(domenico.email === "Domenico.Losurdo@acme.com");
console.assert(domenico.password === "test");


// Héritage
enum Forms {
    Undefined = 0,
    Polygones = 1,
    Circle = 2,
    Straight = 3,
    Segment = 4,
};

class Form {
    type: Forms = Forms.Undefined;
};

class Rectangle extends Form {
    h: Number = 0;
    w: Number = 0;
};

class Square extends Rectangle {
    side: Number = 0;
};


/**
 * Interface donne un contrat à un type.
 * Les interfaces permettent de définir la structure d'un objet.
 */

interface IPerson {
    username: String;
    email: String;
    readonly signup_date: Date;
}

const user1: IPerson = {
    username: Member.fromAuthor(author)["username"],
    email: Member.fromAuthor(author)["email"],
    signup_date: Member.fromAuthor(author)["signup_date"],
}

Le fichier tsconfig.json

tsconfig.json

{
  /* Visit https://aka.ms/tsconfig to read more about this file */
  "compileOnSave": true,

  "compilerOptions": {
    "target": "es2016",
    "module": "CommonJS",
    "noEmitOnError": true,
    "strict": true,
    "noImplicitAny": true,
    "esModuleInterop": true
  }
}

Modules

Les modules permettent d’organiser le code en plusieurs fichiers.

Exemple de cote :

// Dans un fichier math.ts
export const add = (a: number, b: number): number => a + b;

// Dans un autre fichier
import { add } from './math';
let result = add(2, 3);

Promesses

Les promesses sont utilisées pour effectuer des opérations asynchrones.

Exemple de cote :

const promise = new Promise<string>((resolve) => {
    // Code asynchrone ici
    resolve("Succès");
});

promise.then((result) => {
    console.log(result);
});

async/await

L’async/await simplifie la gestion des promesses.

Exemple de cote :

const fetchData = async (): Promise<void> => {
    const result = await someAsyncFunction();
    console.log(result);
};

Génériques

Les génériques permettent de créer des composants réutilisables avec des types dynamiques.

Exemple de cote :

const identity = <T>(arg: T): T => arg;

const output = identity<string>("hello");
console.log(output);