5 types utilitaires TypeScript que vous devriez connaître

Le système de types de TypeScript devient véritablement puissant lorsque vous découvrez les types utilitaires—des assistants intégrés qui transforment les types existants sans les réécrire. Si vous vous êtes déjà retrouvé à dupliquer des interfaces ou à lutter avec des modifications de types, ces cinq types utilitaires essentiels changeront votre façon d’écrire du code TypeScript.
Points clés à retenir
- Les types utilitaires transforment les types existants sans les réécrire, réduisant la duplication de code
- Partial rend toutes les propriétés optionnelles, parfait pour les opérations de mise à jour
- Required impose toutes les propriétés, garantissant des structures de données complètes
- Pick et Omit aident à créer des interfaces ciblées en sélectionnant ou excluant des propriétés
- Readonly empêche les mutations accidentelles, essentiel pour les modèles de données immuables
Que sont les types utilitaires TypeScript et pourquoi sont-ils importants
Les types utilitaires sont des types génériques pré-construits de TypeScript qui construisent de nouveaux types en transformant ceux existants. Au lieu de créer manuellement des variations de vos interfaces, ces utilitaires vous permettent de dériver de nouveaux types avec des modifications spécifiques—rendant votre code plus maintenable et réduisant la duplication de types.
Nous explorerons cinq types utilitaires fondamentaux qui résolvent des problèmes courants du monde réel : Partial, Required, Pick, Omit, et Readonly. Chacun répond à des scénarios spécifiques que vous rencontrez quotidiennement dans le développement TypeScript.
Partial<T> : Rendre toutes les propriétés optionnelles en TypeScript
Le type utilitaire Partial transforme toutes les propriétés d’un type en optionnelles, parfait pour les opérations de mise à jour où vous ne modifiez que des champs spécifiques.
Quand utiliser Partial pour les mises à jour de formulaires
Considérez une mise à jour de profil utilisateur où les utilisateurs peuvent modifier des champs individuels sans envoyer l’objet entier :
interface User {
id: string;
name: string;
email: string;
avatar: string;
lastLogin: Date;
}
function updateUserProfile(userId: string, updates: Partial<User>) {
// Met à jour uniquement les champs fournis
return api.patch(`/users/${userId}`, updates);
}
// Utilisation - mise à jour de l'email uniquement
updateUserProfile("123", { email: "new@email.com" });
Exemple de type Partial avec du code du monde réel
Les mises à jour d’état React bénéficient considérablement de Partial :
const [user, setUser] = useState<User>(initialUser);
const updateUser = (updates: Partial<User>) => {
setUser(prev => ({ ...prev, ...updates }));
};
// Met à jour uniquement des champs spécifiques
updateUser({ name: "Jane Doe", avatar: "new-avatar.jpg" });
Required<T> : Imposer toutes les propriétés en TypeScript
Required fait l’opposé de Partial—il rend toutes les propriétés optionnelles obligatoires, garantissant des structures de données complètes.
Convertir les propriétés optionnelles en obligatoires
Ceci s’avère précieux pour la validation de configuration :
interface DatabaseConfig {
host?: string;
port?: number;
username?: string;
password?: string;
}
// S'assurer que toutes les valeurs de configuration existent avant la connexion
type ValidatedConfig = Required<DatabaseConfig>;
function connectDatabase(config: ValidatedConfig) {
// Toutes les propriétés sont garanties d'exister
return createConnection(config);
}
Le type Required en action
La soumission de formulaires nécessite souvent des données complètes :
interface RegistrationForm {
username?: string;
email?: string;
password?: string;
terms?: boolean;
}
type CompleteRegistration = Required<RegistrationForm>;
function submitRegistration(data: CompleteRegistration) {
// Tous les champs doivent être remplis
api.post('/register', data);
}
Discover how at OpenReplay.com.
Pick<T, K> : Sélectionner des propriétés spécifiques depuis des types
Pick crée un nouveau type en sélectionnant uniquement les propriétés spécifiées, idéal pour créer des interfaces ciblées.
Créer des sous-ensembles de types ciblés avec Pick
Extrayez uniquement ce dont vous avez besoin pour des composants spécifiques :
interface Article {
id: string;
title: string;
content: string;
author: string;
publishedAt: Date;
tags: string[];
}
// Le composant Card n'a besoin que de ces champs
type ArticlePreview = Pick<Article, 'id' | 'title' | 'author'>;
function ArticleCard({ article }: { article: ArticlePreview }) {
return (
<div>
<h3>{article.title}</h3>
<p>par {article.author}</p>
</div>
);
}
Pick vs Omit : Choisir la bonne approche
Utilisez Pick quand vous avez besoin de peu de propriétés, Omit quand vous excluez peu de propriétés :
// Pick : Quand vous avez besoin de 2-3 propriétés d'un type volumineux
type UserSummary = Pick<User, 'id' | 'name'>;
// Omit : Quand vous avez besoin de la plupart des propriétés sauf quelques-unes
type PublicUser = Omit<User, 'password'>;
Omit<T, K> : Exclure des propriétés des types TypeScript
Omit crée un type en excluant les propriétés spécifiées, parfait pour supprimer des champs sensibles ou internes.
Supprimer des données sensibles avec Omit
Protégez les informations sensibles dans les réponses d’API :
interface UserAccount {
id: string;
email: string;
password: string;
creditCard: string;
publicProfile: boolean;
}
// Supprime les champs sensibles pour l'API publique
type PublicUserData = Omit<UserAccount, 'password' | 'creditCard'>;
function getPublicProfile(userId: string): Promise<PublicUserData> {
return api.get(`/users/${userId}/public`);
}
Bonnes pratiques du type utilitaire Omit
Combinez avec d’autres utilitaires pour des modèles puissants :
// Supprime les champs internes et rend les restants optionnels
type UserUpdatePayload = Partial<Omit<User, 'id' | 'createdAt'>>;
Readonly<T> : Créer des types immuables en TypeScript
Readonly rend toutes les propriétés immuables, empêchant les mutations accidentelles et imposant l’intégrité des données.
Prévenir les mutations accidentelles avec Readonly
Essentiel pour la gestion d’état et la configuration :
interface AppConfig {
apiEndpoint: string;
version: string;
features: string[];
}
type ImmutableConfig = Readonly<AppConfig>;
const config: ImmutableConfig = {
apiEndpoint: "https://api.example.com",
version: "1.0.0",
features: ["auth", "payments"]
};
// Erreur TypeScript : Cannot assign to 'apiEndpoint' because it is a read-only property
config.apiEndpoint = "https://new-api.com"; // ❌
Propriétés Readonly et props React
Garantissez que les props restent inchangées :
type UserCardProps = Readonly<{
user: User;
onSelect: (id: string) => void;
}>;
function UserCard({ user, onSelect }: UserCardProps) {
// Les props sont immuables dans le composant
return <div onClick={() => onSelect(user.id)}>{user.name}</div>;
}
Combiner plusieurs types utilitaires pour des modèles avancés
Les types utilitaires deviennent encore plus puissants lorsqu’ils sont combinés :
interface DatabaseRecord {
id: string;
createdAt: Date;
updatedAt: Date;
deletedAt?: Date;
data: Record<string, unknown>;
}
// Crée un type pour les nouveaux enregistrements : pas d'horodatage, données partielles
type NewRecord = Omit<DatabaseRecord, 'id' | 'createdAt' | 'updatedAt'> & {
data: Partial<DatabaseRecord['data']>;
};
// Type de mise à jour : tout optionnel sauf l'ID
type UpdateRecord = Partial<Omit<DatabaseRecord, 'id'>> & Pick<DatabaseRecord, 'id'>;
Conclusion
Ces cinq types utilitaires—Partial, Required, Pick, Omit, et Readonly—forment la base du développement TypeScript efficace. Ils éliminent les définitions de types répétitives, imposent la sécurité des types, et rendent votre code plus maintenable.
Commencez à intégrer ces modèles dans votre base de code. Débutez avec Partial pour les opérations de mise à jour, utilisez Omit pour créer des interfaces publiques sûres, et exploitez Readonly pour prévenir les bugs. À mesure que vous devenez à l’aise, combinez-les pour créer des transformations de types sophistiquées qui correspondent parfaitement aux besoins de votre application.
FAQ
Oui, vous pouvez imbriquer les types utilitaires pour créer des transformations complexes. Par exemple, Partial et Omit fonctionnent bien ensemble pour créer des charges utiles de mise à jour qui excluent certains champs tout en rendant d'autres optionnels.
Non, les types utilitaires sont purement des constructions au moment de la compilation. TypeScript supprime toutes les informations de type pendant la compilation, donc les types utilitaires n'ont aucun impact sur les performances à l'exécution.
L'extension d'interface crée de nouveaux types en ajoutant des propriétés, tandis que les types utilitaires transforment les types existants. Les types utilitaires offrent plus de flexibilité pour modifier des types que vous ne contrôlez pas ou créer des variations de types existants.
Oui, TypeScript vous permet de créer des types utilitaires personnalisés en utilisant les types mappés, les types conditionnels et les types littéraux de template. Commencez avec les utilitaires intégrés et créez des personnalisés lorsque vous identifiez des modèles répétés.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.