Обидва означають «тут може бути будь-яке значення», але з протилежним ставленням до перевірок:
anyвимикає перевірку типів. З ним можна робити що завгодно - викликати методи, звертатися до полів, передавати куди завгодно. Компілятор мовчить, а помилка вилізе під час виконання.unknown- безпечний аналог: присвоїти в нього можна будь-що, але використати значення не можна, доки не доведете, що воно потрібного типу.
const a: any = JSON.parse(text);
a.user.name.toUpperCase(); // компілюється - і може впасти
const u: unknown = JSON.parse(text);
u.user; // помилка компіляції
if (typeof u === 'object' && u !== null && 'user' in u) {
// тут TypeScript знає більше
}
Чому any шкідливий: він «заразний». Значення, отримане з any, теж any, і відсутність перевірок непомітно розповзається кодом.
Коли що:
unknown- для даних ззовні:JSON.parse, відповідь API,catch (error)(у строгому режиміerrorі такunknown), значення зlocalStorage. Звужуєте перевірками або схемою валідації (Zod).any- як тимчасовий захід при міграції з JavaScript, з коментарем і планом прибрати.
У tsconfig варто тримати "strict": true (він вмикає noImplicitAny), а лінтер налаштувати так, щоб явний any був помітним.