Suggest an editImprove this articleRefine the answer for “unknown vs any”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`unknown`** is a safe alternative to `any`: it says "I do not know what this value is, so you must prove its type before using it", and it does not allow calling any methods without a check. **Key point:** despite this, `unknown` stops being safe if it is forcibly cast with `as` or spread too widely without narrowing - in that case it effectively turns into `any` in disguise.Shown above the full answer for quick recall.Answer (EN)Image## 1. What `unknown` does > `unknown` is a **safe alternative** to `any`. > It says: "I do not know what this value is, **so you must prove its type before using it**". Example: ```javascript let value: unknown = "hello"; value.toUpperCase(); // Error: Object is of type 'unknown' if (typeof value === "string") { value.toUpperCase(); // OK, the type is proven } ``` Unlike `any`, TypeScript **does not allow doing anything** until you refine (narrow) the type. That is what makes `unknown` *safe by default*. --- ## 2. Why `unknown` is safer than `any` | Behavior | `any` | `unknown` | |---|---|---| | Can call methods without a check | Yes | No | | Can be assigned to other types | No restrictions | Only after a check | | The IDE suggests properties | No | No (until checked) | | Requires type narrowing | No | Yes | | Can cause runtime errors | Often | Only if the checks are bypassed | Example: ```javascript let a: any = "hello"; let u: unknown = "hello"; a.foo(); // TS lets it through -> crashes at runtime u.foo(); // TS does not allow it -> safe ``` --- ## 3. Why `unknown` can still be used **badly** Although `unknown` is safer, **everything depends on what you do with it**. If you **forcibly break the typing**, `unknown` stops being safe. --- ### Mistake 1: Forced casting with `as` ```javascript let data: unknown = "Hello"; const num = data as number; // a forced cast console.log(num.toFixed(2)); // a runtime error ``` The cast (`as number`) bypasses all of TS's checks. That is, you have **returned to the behavior** of `any`. **Conclusion:** `unknown` is safe as long as you do not force TS to "take your word for it". --- ### Mistake 2: Spreading `unknown` widely If you return `unknown` from functions or store it in data structures, the type system loses context. Example: ```javascript function parseJSON(str: string): unknown { return JSON.parse(str); } const result = parseJSON('{"id":1,"name":"Alex"}'); // result: unknown console.log(result.name); // an error, until you check it ``` This is *safe*, but **inconvenient** - you are forced to manually narrow the type everywhere. If there are many such values, this leads to **typing chaos**. --- ### Mistake 3: Overly generic function types If everything in an API function is declared as `unknown`, you **lose the usefulness of typing** - the IDE no longer knows what the function returns. ```javascript function getUser(): unknown { return { name: "Alex", age: 30 }; } const user = getUser(); user.name; // Error - TS does not know it is an object ``` The code is safe, but useless: TS protects against mistakes but does not help you develop. --- ### Mistake 4: Assigning `unknown` without narrowing ```javascript let data: unknown = 42; let str: string = data; // Error: Type 'unknown' is not assignable to type 'string' ``` It is good that TypeScript **catches this**, but if you write `as string`, the logic still **breaks**: ```javascript let str = data as string; console.log(str.toUpperCase()); // a runtime error ``` --- ## 4. How to use `unknown` correctly **Use** `unknown` **as a safety barrier** - at the boundaries with *external data*, where you cannot trust the types (an API, JSON, user input). Example: ```javascript function parse<T>(json: string): T { const data: unknown = JSON.parse(json); if (isUser(data)) { return data; // TS is now confident } throw new Error("Invalid user data"); } ``` Here: - `unknown` is the safe starting point - `isUser()` is the *type guard* - `T` is the typed value we return --- ## 5. When `unknown` is better than `any`, and when it is not | Situation | `unknown` is better | `any` is better | |---|---|---| | Receiving data from an API | Yes | No | | Quick debugging or temporary code | Possible, but cumbersome | Yes (temporarily) | | Writing universal functions | Yes (narrow the type later) | No | | Legacy code with no time for strict checks | Inconvenient | Temporarily acceptable | | Public libraries | Yes (external input is `unknown`) | No | --- ## 6. A correct example with checks ```javascript function isUser(value: unknown): value is { id: number; name: string } { return ( typeof value === "object" && value !== null && "id" in value && "name" in value ); } const data: unknown = JSON.parse('{"id":1,"name":"Alex"}'); if (isUser(data)) { console.log(data.name.toUpperCase()); // safe } else { console.error("Invalid user"); } ``` Here `unknown` does its job - it protects against the wrong type until you prove otherwise. --- ## 7. The fundamental difference in philosophy | | `any` | `unknown` | |---|---|---| | Philosophy | "I know what I'm doing" | "I do not yet know what this is" | | Safety | absent | maximal | | Use case | temporary solutions, legacy code | external data, APIs, dynamism | | Type checking | disabled | mandatory | | Breaks the type contract | easily | only through `as` | --- ## Summary | Question | Answer | |---|---| | Why is `unknown` safer? | It **forces** you to check the type before using it. | | Why can it be dangerous? | If you **bypass the checks** with `as` or use it too broadly, the point of typing is lost. | | Where is it appropriate? | At the boundaries of an application: parsing JSON, user input, unpredictable APIs. | | The main idea | `unknown` is a "safe unknown". You cannot use the value until you prove it is the type you need. | --- **Just remember:** > `any` says "I know better than TypeScript". > `unknown` says "TypeScript, help me make sure". > > But if you "trick" the compiler yourself (via `as`), > then `unknown` stops being safe and becomes a regular `any` in disguise.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.