📧 Reste informé(e) !

Reçois les derniers articles et conseils EasyAngularKit directement dans ta boîte mail.

S'inscrire gratuitement

~4 min de lecture

TypeScript : Arrête d'utiliser any (et fais ça à la place)

Utiliser any en TypeScript, c'est comme mettre une ceinture de sécurité sans l'attacher. Tu as l'impression d'être protégé, mais au premier choc, tu comprends que ça servait à rien.

Quand tu écris any, tu dis explicitement à TypeScript : "T'inquiète, je gère." Spoiler : tu ne gères pas. Personne ne gère.


1. Ce que tu perds avec any

Zéro autocomplétion

Avec any, ton IDE devient muet. Pas de suggestions, pas de propriétés proposées. Tu codes à l'aveugle.

function processUser(user: any) {
    // Ton IDE ne te propose rien ici
    console.log(user.???);
}

Des erreurs invisibles

Le vrai danger : les typos passent complètement inaperçues.

type User = {
    readonly id: number;
    readonly name: string;
    readonly email: string;
};

function displayUser(user: any) {
    // Typo sur "email" → aucune erreur, aucun warning
    console.log(user.emial);
}

TypeScript ne bronche pas. ESLint non plus. Tu découvres le bug en production quand un utilisateur te signale que son email n'apparaît pas.

Le problème en équipe

Quand tu bosses seul sur deux fichiers, ça passe encore. Sur un projet conséquent avec une équipe, c'est ingérable. Personne n'est dans ta tête, personne ne va relire chaque ligne pour vérifier que user.adress aurait dû être user.address.


2. Démonstration : appel API avec JSON Placeholder

Prenons un cas concret. Tu appelles une API qui retourne des utilisateurs :

// ❌ Ce qu'on voit trop souvent
@Injectable()
export class HttpUserAdapter {
    private readonly _http = inject(HttpClient);

    getUsers(): Observable<any> {
        return this._http.get<any>('https://jsonplaceholder.typicode.com/users');
    }
}

Dans ton composant :


@Component({
    template: `
    @for (user of users(); track user.id) {
      <p>{{ user.name }} - {{ user.emial }}</p>  <!-- Typo ! -->
    }
  `
})
export class UserList {
    private readonly _userAdapter = inject(HttpUserAdapter);

    protected readonly users = toSignal(this._userAdapter.getUsers(), {initialValue: []});
}

Résultat : aucune erreur à la compilation, aucun warning dans la console. Juste un affichage cassé que tu découvriras peut-être. Ou pas.


3. La fausse bonne idée : any[]

Premier réflexe de beaucoup de devs :

export class HttpUserAdapter {
    private readonly _http = inject(HttpClient);

    getUsers(): Observable<any[]> {
        return this._http.get<any[]>('https://jsonplaceholder.typicode.com/users');
    }
}

Tu sais maintenant que c'est une liste. Bravo. Mais chaque élément reste un any. Tu n'as toujours aucune protection sur les propriétés.


4. La vraie solution : unknown

unknown, c'est "je ne sais pas ce que c'est, et je vais devoir le vérifier".

export class HttpUserAdapter {
    private readonly _http = inject(HttpClient);

    getUsers(): Observable<unknown[]> {
        return this.#http.get<unknown[]>('https://jsonplaceholder.typicode.com/users');
    }
}

Maintenant, si tu essaies d'utiliser directement les données :

// ❌ TypeScript refuse
const users = await firstValueFrom(this._userAdapter.getUsers());
console.log(users[0].name); // Error: 'unknown' is not assignable to type...

TypeScript te force à vérifier le type avant de l'utiliser. C'est exactement ce qu'on veut.


5. Créer un Type Guard

Pour transformer un unknown en type connu, tu crées un type guard :

type User = {
    readonly id: number;
    readonly name: string;
    readonly email: string;
};

function isUser(value: unknown): value is User {
    return (
        value !== null &&
        typeof value === 'object' &&
        'id' in value &&
        'name' in value &&
        'email' in value &&
        typeof (value as User).id === 'number' &&
        typeof (value as User).name === 'string' &&
        typeof (value as User).email === 'string'
    );
}

Pourquoi value !== null && typeof value === 'object' ? Parce que typeof null retourne 'object' en JavaScript. Un classique.

Utilisation :

export class HttpUserAdapter {
    getUsers(): Observable<User[]> {
        return this._http.get<unknown[]>('https://jsonplaceholder.typicode.com/users').pipe(
            map(results => results.filter(isUser))
        );
    }
}

Maintenant :

  • TypeScript connaît le type exact
  • L'autocomplétion fonctionne
  • Les typos sont détectées à la compilation
  • Les données mal formées sont filtrées

6. Le problème des type guards manuels

Pour un objet à 3 propriétés, ça va. Mais quand tu en as 15, 20, 30... ça devient vite laborieux et source d'erreurs.

C'est là qu'intervient Zod 😍.


7. Zod : la validation de schéma simplifiée

Zod te permet de définir un schéma et d'en dériver automatiquement le type TypeScript :

import {z} from 'zod';

const UserSchema = z.object({
    id: z.number(),
    name: z.string(),
    email: z.string().email(),
});

// Le type est inféré automatiquement
type User = z.infer<typeof UserSchema>;

Validation avec parse

export class HttpUserAdapter {
    getUsers(): Observable<User[]> {
        return this._http.get<unknown[]>('https://jsonplaceholder.typicode.com/users').pipe(
            map(results => z.array(UserSchema).parse(results.filter(isUser)))
        );
    }
}

Si les données ne correspondent pas au schéma, Zod lance une erreur explicite :

ZodError: [
  {
    "code": "invalid_type",
    "expected": "string",
    "received": "undefined",
    "path": ["email"],
    "message": "Required"
  }
]

Tu sais exactement quel champ pose problème, sur quel objet, et pourquoi.

Validation douce avec safeParse

Si tu préfères gérer les erreurs sans exception :

const result = UserSchema.safeParse(data);

if (result.success) {
    // result.data est typé User
    console.log(result.data.email);
} else {
    // result.error contient les détails
    console.error(result.error.issues);
}

Filtrer les données invalides

export class HttpUserAdapter {
    getUsers(): Observable<User[]> {
        return this._http.get<unknown[]>('https://jsonplaceholder.typicode.com/users').pipe(
            map(results =>
                results
                    .map(item => UserSchema.safeParse(item))
                    .filter((result): result is { success: true; data: User } => result.success)
                    .map(result => result.data)
            )
        );
    }
}

8. Bonus Angular : httpResource avec parser intégré

Pour ceux qui utilisent httpResource (experimental), la validation s'intègre directement :

import {httpResource} from '@angular/common/http';

@Component({
    template: `
    @if (usersResource.value(); as users) {
      @for (user of users; track user.id) {
        <div>{{ user.name }} - {{ user.email }}</div>
      }
    }
  `
})
export class UserList {
    protected readonly usersResource = httpResource<User[]>({
        url: 'https://jsonplaceholder.typicode.com/users',
        parse: z.array(UserSchema).parse,
    });
}

Le parser est appelé automatiquement sur la réponse. Si les données sont invalides, tu le sais immédiatement.


9. Récapitulatif

Approche Avantages Inconvénients
any Aucun Tout : pas de typage, pas d'autocomplétion, bugs silencieux
unknown + type guard manuel Contrôle total, zero dépendance Verbeux pour les gros objets
Zod Concis, messages d'erreur clairs, type inféré Dépendance externe
Zod mini Comme Zod, bundle réduit API légèrement restreinte

10. La règle à retenir

any, c'est interdit.

Ce n'est pas une question de purisme. C'est une question de professionnalisme. Tu ne codes pas seul dans ta grotte. Ton code sera relu, maintenu, étendu par d'autres (ou par toi dans 6 mois, ce qui revient au même).

Les outils existent. unknown est natif. Zod prend 5 minutes à configurer. Il n'y a plus d'excuse.

11. Optimisation : zod/mini pour réduire le bundle

Si jamais tu souhaites optimiser la taille de ton bundle tout en utilisant Zod, voici ce que je peux te proposer :

🔗 https://www.easyangularkit.com/blog/optimisation-bundle-zod-mini


📧 Reste informé(e) !

Reçois les derniers articles et conseils EasyAngularKit directement dans ta boîte mail.

S'inscrire gratuitement

EasyAngularKit

Formation complète pour maîtriser Angular et développer des applications web modernes.

Navigation

Contact

Légal

© 2026 Easy Angular Kit. Tous droits réservés.