Les décorateurs de paramètres permettent principalement d'ajouter des metadata à la classe pour que les décorateurs de méthode puissent s'en servir.
Mémorisation des résultats
Le décorateur ci-dessous construit progressivement un objet de mémorisation permettant de "mapper" les paramètres au dernier résultat obtenu afin d'éviter de refaire le même calcul inutilement.
constMemoize= () => (target, key:string) => {constmemory= {};constoriginal= target[key]; target[key] =function (...args) {/* Retrieve last returned value from memory if available. */constvalue= memory[args.toString()];if (value !==undefined) {return value; }constresult=original.apply(this, args); memory[args.toString()] = result;return result; };};classCalculator { @Memoize()sum(a, b) {console.log('computing...');return a + b; }}constcalculator=newCalculator();console.log(calculator.sum(1,2));// computing...// 3console.log(calculator.sum(1,2));// 3console.log(calculator.sum(1,2));// 3console.log(calculator.sum(2,2));// computing...// 4console.log(calculator.sum(1,2));// 3
Contract checking en runtime
import'reflect-metadata';const_contractDictMetadataKey='__contractDict';constApplyContracts= () => (target, key:string) => {constoriginalMethod= target[key];constcontractDict=Reflect.getOwnMetadata(_contractDictMetadataKey, target, key); target[key] =function (...argList) {if (contractDict !==undefined) {argList.forEach((value, index) => {constcontract= contractDict[index];if (contract ===undefined) {return; }if (!contract(value)) { throw new Error(`Value '${value}' does not respect contract for \`${target.constructor.name}.${key}(param_${index})\`.`);
} }); }returnoriginalMethod(...argList); }};constContract= (contract: (value:any) =>boolean) => (target, key, index):any=> {let contractDict =Reflect.getOwnMetadata(_contractDictMetadataKey, target, key);if (contractDict ===undefined) { contractDict = {}; } contractDict[index] = contract;Reflect.defineMetadata(_contractDictMetadataKey, contractDict, target, key);};constisPositive= value => value >0;classUtils { @ApplyContracts()double(@Contract(isPositive) number:number):number {return number *2; }}console.log(newUtils().double(2)); // 4// Error: Value '0' does not respect contract for `Utils.double(param_0)`.console.log(newUtils().double(0));