any, unknown: различия
anyполностью отключает проверку типов и позволяет делать с переменной что угодно, тогда какunknown— безопасная альтернатива: значение можно присвоить чему угодно, но использовать его методы и свойства можно только после narrowing (сужения типа).
Зачем нужно
Понимание разницы между any и unknown критично для написания безопасного кода. any — это «дыра» в системе типов, unknown — безопасная зона для работы с данными неизвестного происхождения (JSON, пользовательский ввод, API).
Где используется
any— миграция JS → TS, временные заглушки, работа с нетипизированными библиотекамиunknown— обработка внешних данных:JSON.parse, catch блоки ошибок, API-ответы- Оба — в generic-коде где тип намеренно не важен (но лучше
unknown)
Основной контент
Сравнение поведения
// any — TypeScript «закрывает глаза»
let a: any = "hello";
a.toUpperCase(); // OK (компилятор)
a.nonExistentMethod; // OK (компилятор) — упадёт в рантайме!
a = 42; // OK
const b: string = a; // OK — any совместим с любым типом
// unknown — TypeScript требует проверки
let u: unknown = "hello";
// u.toUpperCase(); // Error: Object is of type 'unknown'
// u.nonExistentMethod; // Error
// const c: string = u; // Error — unknown не совместим с string
// Нужно сначала сузить тип:
if (typeof u === "string") {
u.toUpperCase(); // OK — u: string здесь
}
Присваивание: симметрия vs асимметрия
// any принимает всё и совместим со всем
let a: any;
a = "string"; // OK
a = 42; // OK
a = null; // OK
const s: string = a; // OK — any → string
const n: number = a; // OK — any → number
// unknown принимает всё, но сам не совместим с конкретными типами
let u: unknown;
u = "string"; // OK
u = 42; // OK
// const s: string = u; // Error — unknown → string без narrowing
const a2: any = u; // OK — unknown → any
const u2: unknown = u; // OK — unknown → unknown
unknown в catch блоках (TS 4.0+)
// До TS 4.0 — error было any
try {
JSON.parse("invalid");
} catch (e) {
// e: any (старый стиль) или unknown (с useUnknownInCatchVariables: true)
if (e instanceof Error) {
console.log(e.message); // безопасно
} else if (typeof e === "string") {
console.log(e);
}
}
unknown для парсинга JSON
function parseConfig(json: string): Record<string, unknown> {
const parsed: unknown = JSON.parse(json);
if (typeof parsed !== "object" || parsed === null) {
throw new Error("Config must be an object");
}
return parsed as Record<string, unknown>;
}
// Vs небезопасный вариант:
function unsafeParse(json: string): any {
return JSON.parse(json); // any — проверок нет
}
Когда допустим any
// 1. Временно при миграции JS → TS
function legacyFn(data: any): any {
return data; // TODO: типизировать
}
// 2. Debug-утилиты
function log(...args: any): void {
console.log(...args);
}
// 3. Обёртка над нетипизированной библиотекой (временно)
declare const oldLib: any;
Частые ошибки
- Использовать
anyвместоunknownдля внешних данных — теряется вся защита типов. - Не сужать
unknownперед использованием —unknownтребуетtypeof,instanceofили type guard. catch (e: any)— в современном TypeScript лучше обрабатыватьeкакunknownи делать narrowing.anyвместоunknown— в generic rest-параметрах часто достаточноunknown.
Альтернативная позиция: никогда any — только unknown
"Unknown — это более строгий тип, чем any. Дело в том, что unknown будет чекаться, а any не будет. В этом и разница."
автор использует any практически никогда. Даже в .d.ts для словарей-словарей:
// Плохо избегает
type Dict1 = Record<string, any>;
// Хорошо — заставляет вызывающего сузить тип
type Dict2 = Record<string, unknown>;
Принцип: any — это дыра в системе типов. Если намеренно отключаешь проверку — выбери unknown и сделай явный narrowing/cast. Это видно в код-ревью.
Связанные темы
- any unknown never void
- Type Guards -- typeof и instanceof
- Пользовательские Type Guards
- Assertion Functions
- TS vs JS -- философия Тимура
- _MOC TypeScript
Источники
- 🎓 TypeScript vs JavaScript: как лучше писать типы · 2025-11-08 · YouTube
- Позиция автора:
anyне использовать никогда. Толькоunknown+ явное сужение.
- Позиция автора: