Contraintes génériques (extends)

Exiger qu’un paramètre de type respecte une forme précise.

Sur cette page

Exemple

#
TypeScript
function longest<T extends { length: number }>(a: T, b: T): T {
  return a.length >= b.length ? a : b
}

console.log(longest('HTML', 'JavaScript'))
console.log(longest([1, 2, 3], [4, 5]))
Résultat
JavaScript
[1, 2, 3]

Définition et utilisation

#

Un paramètre de type sans contrainte peut être n’importe quoi, donc à l’intérieur de la fonction, vous ne pouvez pas supposer qu’il possède un champ particulier. La notation <T extends { length: number }> signifie : « T peut être n’importe quel type, mais il doit avoir un champ length ».

Grâce aux contraintes, une fonction générique peut utiliser en toute sécurité les propriétés du paramètre, et le compilateur rejette les appels avec des types qui ne les possèdent pas.

Une combinaison très répandue est celle avec keyof : <T, K extends keyof T> garantit que le second argument est l’une des clés du premier objet.

Syntaxe

#
Syntaxe
function name<T extends Condition>(param: T) { … }

Plus d’exemples

#
Une clé qui existe à coup sûr
TypeScript
function pluck<T, K extends keyof T>(items: T[], key: K): T[K][] {
  return items.map((item) => item[key])
}

const students = [
  { name: 'Léa', level: 7 },
  { name: 'Lucas', level: 3 }
]

console.log(pluck(students, 'name'))
console.log(pluck(students, 'level'))
Résultat
['Léa', 'Lucas']
[7, 3]
Un appel rejeté par la contrainte
TypeScript
longest(10, 20)
// Erreur : Argument of type 'number' is not assignable to parameter of type '{ length: number; }'.

Bonnes pratiques

#
  • Ne limitez les paramètres de type qu’autant que le code de la fonction l’exige réellement. Une contrainte trop étroite réduit l’utilité de la fonction.
  • Le motif K extends keyof T est la base des fonctions sûres qui travaillent sur les clés d’objets.

Entrées associées

#

Vous voyez une erreur ou il manque un exemple ? Écrivez-nous.