JavaScript / TypeScript
Fonctions utilitaires, patterns de manipulation de données et outils TypeScript pour le quotidien.
⚡ Utilitaires courants
Debounce
Retarde l’exécution d’une fonction jusqu’après un temps d’inactivité.
function debounce(fn, ms = 300) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), ms);
};
}
// Usage : rechercher après 300 ms d'inactivité
const recherche = debounce((query) => {
fetch(`/api/search?q=${query}`).then(renderResults);
}, 300);
input.addEventListener('input', (e) => recherche(e.target.value));Throttle
Exécute une fonction au maximum une fois toutes les ms millisecondes.
function throttle(fn, ms = 300) {
let last = 0;
return (...args) => {
const now = Date.now();
if (now - last >= ms) {
last = now;
fn(...args);
}
};
}
// Usage : limiter le scroll handler
window.addEventListener('scroll', throttle(() => {
updateScrollIndicator();
}, 100));Unique par clé
Crée un tableau sans doublons — natif avec Set, ou avec Map pour préserver l’ordre et les objets complexes.
// Basique (ordre non garanti)
[...new Set([3, 1, 2, 1, 3, 2])]; // [3, 1, 2]
// Ordre préservé + clé custom (ex: objets par id)
function uniqueBy(arr, keyFn) {
const seen = new Map();
return arr.filter(item => {
const key = keyFn(item);
if (seen.has(key)) return false;
seen.set(key, true);
return true;
});
}
const users = [
{ id: 1, nom: 'Alice' },
{ id: 2, nom: 'Bob' },
{ id: 1, nom: 'Alice Duplicate' },
];
uniqueBy(users, u => u.id);
// [{ id: 1, nom: 'Alice' }, { id: 2, nom: 'Bob' }]GroupBy
Regroupe les éléments d’un tableau par une clé calculée.
function groupBy(arr, keyFn) {
return arr.reduce((groups, item) => {
const key = keyFn(item);
(groups[key] = groups[key] || []).push(item);
return groups;
}, {});
}
const people = [
{ nom: 'Alice', role: 'dev' },
{ nom: 'Bob', role: 'dev' },
{ nom: 'Carol', role: 'design' },
];
groupBy(people, p => p.role);
// {
// dev: [{ nom: 'Alice', role: 'dev' }, { nom: 'Bob', role: 'dev' }],
// design: [{ nom: 'Carol', role: 'design' }]
// }Chunk
Découpe un tableau en blocs de taille size.
function chunk(arr, size) {
return Array.from({ length: Math.ceil(arr.length / size) }, (_, i) =>
arr.slice(i * size, i * size + size)
);
}
chunk([1, 2, 3, 4, 5, 6, 7], 3);
// [[1, 2, 3], [4, 5, 6], [7]]Pitfall :
chunkavecsize = 0renvoieInfinitydansMath.ceil()→ array infini. Guard :if (size <= 0) return [];
📊 Tableaux
Map / Filter / Reduce — chaînage
// Extraire les noms des utilisateurs actifs, triés par longueur
const noms = users
.filter(u => u.actif)
.map(u => u.nom)
.sort((a, b) => a.length - b.length);
// Aggregate : somme des montants par catégorie
const totals = transactions
.reduce((acc, t) => {
acc[t.categorie] = (acc[t.categorie] || 0) + t.montant;
return acc;
}, {});Immutabilité
Toujours créer de nouveaux tableaux, jamais modifier l’original.
// ❌ Ne jamais faire :
arr.push(item); // mutatif
arr[0] = newValue; // mutatif
arr.sort(); // mutatif (.sort modifie en place !)
// ✅ Toujours faire :
const newArr = [...arr, item];
const replaced = arr.map((v, i) => i === idx ? newValue : v);
const sorted = [...arr].sort((a, b) => a - b);Array.from & flatMap
// Créer un tableau à partir d'un objet itérable
Array.from({ length: 5 }, (_, i) => i + 1); // [1, 2, 3, 4, 5]
// flatMap : map + flatten à un niveau (indispensable)
const mots = ['hello world', 'foo bar'];
mots.flatMap(m => m.split(' ')); // ['hello', 'world', 'foo', 'bar']
// Équivalent manuel (plus verbeux) :
mots.map(m => m.split(' ')).flat();🧩 Objets & destructuring
Destructuring avancé
// Valeurs par défaut
const { host = 'localhost', port = 3000 } = config;
// Renommer à la volée
const { id: userId, nom: userName } = user;
// Destructuring imbriqué
const { data: { users: userList, meta: { page } } } = response;
// Spread pour capturer le reste des propriétés
const { password, ...sansMdp } = user;
// sansMdp = { id: 1, nom: 'Alice' }
// Déstructuring avec guard (objet potentiellement undefined)
const items = parsed.data?.items ?? [];
items.forEach(({ nom, prix }) => console.log(nom, prix));Pitfall : déstructurer un objet
nullouundefinedlèveTypeError. Toujours utiliser un fallback :const { x } = obj ?? {};
Object.entries / keys / values
const config = { debug: true, port: 3000, host: 'localhost' };
// Clés
Object.keys(config); // ['debug', 'port', 'host']
// Valeurs
Object.values(config); // [true, 3000, 'localhost']
// Paires [key, value] — utile pour les boucles filtrées
Object.entries(config)
.filter(([, v]) => typeof v === 'string')
.map(([k, v]) => `${k.toUpperCase()}=${v}`);
// ['HOST=localhost']Spread & copy profonde limitée
// Shallow copy : une seule couche
const clone = { ...original };
// Deep clone limité (JSON) — perd Date, RegExp, undefined, Map, Set
const deep = JSON.parse(JSON.stringify(obj));
// Deep clone robuste (navigateurs modernes)
const safe = structuredClone(obj);
// préserve : Date, RegExp, Map, Set, ArrayBuffer, etc.