AccueilActualités informatiqueLangage de programmation : TypeScript 4.6 se montre plus flexible avec le...

Langage de programmation : TypeScript 4.6 se montre plus flexible avec le constructeur

À peine une semaine après la date prévue, la première bêta de TypeScript 4.6 est sortie. Cette version apporte surtout des modifications sous le capot visant à améliorer l’analyse des types. De plus, elle est moins stricte avec le constructeur des objets enfants qui appellent le constructeur de l’objet parent.

Sommaire

TypeScript, comme JavaScript, interdit pour une bonne raison l’accès dans le constructeur à this avant l’appel de super()car la classe parente y initialise le contenu de l’objet. Cependant, le langage de programmation de Microsoft était jusqu’à présent sans doute un peu trop strict avec les règles et interdisait tout code avant l’appel du constructeur parent, même si celui-ci ne concernait pas l’objet lui-même. this n’accède pas au code.

Cela change avec la version actuelle, après un long travail préparatoire : la pull request correspondante a trois ans et a reçu un gâteau d’anniversaire juste avant la mise en œuvre. Avec l’implémentation, du code est maintenant disponible avant super est autorisé, TypeScript s’assurant qu’il ne peut pas accéder à l’objet par this n’est pas inclus.

Les modifications sous le capot concernent surtout l’attribution et la vérification des types. Ainsi, le langage de programmation déduit le type concret lors de la combinaison de types d’accès indexés avec une map pour l’accès à l’index. Jusqu’à présent, il attribuait tous les types définis dans la map comme affectation possible, comme le montre l’exemple suivant tiré du blog TypeScript :

interface TypeMap {
    "number": number;
    "string": string;
    "boolean": boolean;
}

type UnionRecord<P extends keyof TypeMap> = { [K in P]:
    {
        kind: K;
        v: TypeMap[K];
        f: (p: TypeMap[K]) => void;
    }
}[P];

function processRecord<K extends keyof TypeMap>(record: 
                                                UnionRecord<K>) {
    record.f(record.v);
}

processRecord({
    kind: "string",
    v: "hello!",

    // 'val' used to implicitly have the type 
    // 'string | number | boolean',
    // but now is correctly inferred to just 'string'.
    f: val => {
        console.log(val.toUpperCase());
    }
})

De plus, TypeScript 4.6 apporte une analyse de flux de contrôle améliorée pour les paramètres restants dépendants, où le type d’un paramètre dépend de celui qui le précède :

function func(...args: ["str", string] | ["num", number])

Si le premier paramètre "str" est une chaîne, le deuxième est une chaîne de caractères. Mais si le premier paramètre est "num" le second est une number. TypeScript utilise maintenant cette connaissance dans la suite du code et connaît le type du deuxième dans les blocs qui vérifient le premier paramètre, comme dans l’exemple suivant tiré du blog TypeScript :

type Func = (...args: ["a", number] | ["b", string]) => void;

const f1: Func = (kind, payload) => {
    if (kind === "a") {
        payload.toFixed();  // 'payload' narrowed to 'number'
    }
    if (kind === "b") {
        payload.toUpperCase();  // 'payload' narrowed to 'string'
    }
};

f1("a", 42);
f1("b", "hello");

Pour une analyse plus approfondie des outils via le --generateTrace-l’équipe a publié un analyseur de trace, disponible en tant que projet autonome sur GitHub.

D’autres nouveautés de la version bêta 4.6, comme la vérification améliorée de la profondeur des instanciations récursives, sont disponibles sur le blog TypeScript. La version finale est prévue pour le 22 février.

Plus d'articles