# You Are Lying to Your Compiler. Use "satisfies" Instead of "as".

> Source: <https://dev.to/ogeobubu/you-are-lying-to-your-compiler-use-satisfies-instead-of-as-55j2>
> Published: 2026-09-27 21:07:32+00:00

You are lying to the compiler. It is time to stop.

I am going to say something that might make some of you uncomfortable. Every time you write `as` in TypeScript, you are basically telling the compiler to shut up and trust you. That feels powerful in the moment. It is also how you ship bugs to production.

The `as` keyword does not check anything. It is a command, not a question. You are saying "I know better than you, compiler, and I don't need your help." Sometimes that is true. Most of the time it is not.

TypeScript 4.9 gave us something better. It is called satisfies. Once you understand what it does, you will wonder how you ever lived without it.

**What `as` actually does**

Let me be clear about the mechanics here. When you write:

`const user = { name: "Alice" } as User;`

You are doing a type assertion. You are overriding TypeScript's type inference with your own judgment. The compiler will check that the assertion is plausible. It will not verify that your object actually has all the required properties.

Here is the problem. `as` suppresses errors. It does not catch mistakes. It hides them.

Look at this:

``` js
interface User {
  name: string;
  email: string;
}

const user = {
  name: "Alice",
  username: "alice123"
} as User;
```

TypeScript will not complain. But you just created an object that claims to be a `User` while missing the email property and carrying an extra `username` field. If your code later tries to read `user.email`, you get undefined at runtime.

This is exactly the kind of silent failure TypeScript was supposed to prevent.

**Enter satisfies**

The satisfies operator does something different. Instead of overriding the type, it validates it.

Same example with satisfies:

``` js
const user = {
  name: "Alice",
  email: "alice@example.com"
} satisfies User;
```

If you misspell `email` as `emial`, or forget it entirely, TypeScript throws an error immediately. Your IDE will yell at you. The compiler will refuse to build.

But here is the beautiful part. `satisfies` does not widen your types.

With a type annotation like `const user: User = {...}`, TypeScript treats `user.name as string`. With `satisfies`, TypeScript keeps the literal type. If you wrote `name: "Alice"`, then `user.name` is exactly `"Alice"`, not just string.

**The difference in practice**

Let me show you a real scenario that changed how I write TypeScript.

Imagine you are defining a color palette:

```
type ColorConfig = Record<string, [number, number, number]>;

// With annotation, you lose precision
const colors: ColorConfig = {
  red: [255, 0, 0],
  green: [0, 255, 0],
  blue: [0, 0, 255],
};

colors.red;   // Type: [number, number, number]
colors.pink;  // No error. TypeScript doesn't know "pink" doesn't exist
```

Now with `satisfies`:

``` js
const colors = {
  red: [255, 0, 0],
  green: [0, 255, 0],
  blue: [0, 0, 255],
} satisfies ColorConfig;

colors.red;   // Type: [255, 0, 0]. Precise.
colors.pink;  // Error: Property 'pink' does not exist
```

That second example gives you autocomplete for the actual keys, catches typos, and preserves the exact literal values. This is what TypeScript was always supposed to feel like.

**When you should still use as**

I am not saying `as` is always wrong. There are legit cases where you know more than the compiler.

The classic one is DOM queries:

`const element = document.querySelector("#app") as HTMLDivElement;`

TypeScript cannot possibly know what element is on the page. It returns `Element | null`. You know it is a `div`. This is where `as` earns its keep.

Other legit uses include type guards and certain edge cases where you are avoiding any. But for object literals, config files, and type validation, which is where most of us spend our time, `satisfies` is the better tool.

**The mental model**

Here is how I think about it.

Type annotation (`: Type`) means "this variable is this type. I don't care about the specific value."

`as` means "I know better than you, compiler. Don't check."

`satisfies` means "make sure this value fits this shape, but keep the precise type I inferred."

The third option is almost always what you actually want.

**Stop lying. Start validating.**

The TypeScript community is already moving this direction. There are even lint rule proposals to prefer `satisfies` over `as` for exactly the reasons I described.

Next time you reach for `as`, ask yourself one question. Am I actually smarter than the compiler here, or am I just being lazy?

If it is the second one, try `satisfies`. Your future self will thank you.
