Загрузка…
Загрузка…
TypeScript · middle · сложность 6
any отключает проверку типов: с значением можно делать что угодно, компилятор молчит. unknown тоже принимает любой value, но запрещает использовать его, пока вы не сузите тип. never — тип «этого не должно случиться»: функции, которые не возвращают, и невозможные ветки.
Три имени звучат похоже, но роли противоположные:
any: «выключи проверку». Можно вызывать несуществующие методы. Хуже того, any заразен: результат выражения с any тоже any, дыра расползается по коду.unknown: «безопасный any». Для данных неизвестной формы (ответ API, JSON.parse, catch). Пока не сделаете typeof / instanceof / валидацию — ничего нельзя вызвать.never: «сюда значение не попадёт». Возврат у throw, и exhaustiveness в switch. В never нельзя присвоить обычное значение — именно поэтому он полезен.Практическое правило: почти всегда вместо any нужен unknown плюс проверка.
// any: the compiler shuts off and the error arrives at runtime
const anyData: any = "hello";
anyData.toFixed(2); // compiles... and blows up at runtime
const spread = anyData + 1; // spread is also any
// unknown: accepts everything, but demands a check before use
function processInput(input: unknown): string {
// input.toUpperCase();
// Error: 'input' is of type 'unknown'.
if (typeof input === "string") {
return input.toUpperCase(); // we've verified: here it's string
}
if (typeof input === "number") {
return input.toFixed(2);
}
return "unsupported type";
}
// Real-world unknown: JSON.parse returns any, better to treat it as unknown
const raw: unknown = JSON.parse('{"name":"Ana"}');
// never: functions that never return
function fail(message: string): never {
throw new Error(message);
}
// never in exhaustiveness: guarantees we cover every case
type Role = "admin" | "user";
function describeRole(role: Role): string {
switch (role) {
case "admin": return "Full access";
case "user": return "Limited access";
default: {
const nothing: never = role; // if Role grows, this stops compiling
return nothing;
}
}
}«Заглушить» ошибку типов через any, лишь бы скомпилировалось:
// A junior does this to silence the error:
const response: any = await fetch("/api/user").then((r) => r.json());
console.log(response.name.toUpperCase()); // can blow up at runtime
// Better: unknown + verification
const data: unknown = await fetch("/api/user").then((r) => r.json());
if (typeof data === "object" && data !== null && "name" in data) {
console.log(data.name); // safe access after narrowing
}С any ошибка не исчезает — она просто переезжает из compile time в runtime, худшее место для неё.
any отключает проверку и заражает код; unknown принимает всё, но требует сужения; never маркирует невозможное. Для внешних данных берите unknown.