How to Use satisfies in TypeScript

Learn how to use the satisfies operator in TypeScript to enforce stricter type safety. See comparisons with as and extends, and explore real examples.

What Is satisfies in TypeScript?

The satisfies keyword is a type-checking operator introduced in TypeScript 4.9. It allows you to validate that a value matches a specific type while still preserving the literal and detailed structure of the value itself.

This operator is useful when you want to make sure an object fits a particular shape but don’t want TypeScript to widen the type or throw away extra information. In other words, it helps you keep strong type safety without losing useful data.

Why use satisfies?

The main benefit of using the satisfies keyword is that it gives you both safety and precision.

When you use as, TypeScript may let things slide or widen types in ways you don’t intend. With satisfies, TypeScript checks that your value conforms to the target type at compile time, and it will give an error if it doesn’t.

At the same time, satisfies doesn’t throw away the extra fields or narrow literal types — it keeps them available for IntelliSense and other autocomplete tooling.

Example: How to use satisfies in TypeScript

type User = {
  id: number;
  role: 'admin' | 'user';
};

const admin = {
  id: 1,
  role: 'admin',
  extra: 'metadata' // extra field not part of User
} satisfies User; // Valid: has all required fields of User

// The object passes type checking, but `admin.extra` is still accessible.

In this example, TypeScript confirms that the object has all the required fields from the User type. At the same time, it preserves the extra property and the exact string value 'admin' for later use.

satisfies vs as in TypeScript

Developers often use the as keyword to tell TypeScript to treat a value as a certain type. However, as simply forces the type and does not validate the structure.

const user1 = {
  id: 1
} as User; // No error! But 'role' is missing — this could lead to bugs

TypeScript trusts you with as and skips strict validation. This can lead to runtime issues if something is missing.

With satisfies, TypeScript ensures the object matches the type exactly.

const user2 = {
  id: 1
} satisfies User; // Compile-time error: Property 'role' is missing

This is a safer approach because it ensures your object truly matches the type. That’s why many developers are now preferring satisfies over as.

satisfies vs extends in TypeScript

The extends keyword is used when you’re working with types, not values. It’s mainly used to build on top of other types, for example, to create a more specific version of a base type.

Here’s how extends works in type declarations:

type User = {
  id: number;
  role: 'admin' | 'user';
};

type Admin = User & {
  accessLevel: number;
};

// or using extends syntax for generics
type ApiResponse<T> = {
  status: number;
  data: T;
};

type UserResponse = ApiResponse<User>;

In the first example, Admin extends User by adding a new field accessLevel. This lets you reuse and build on existing types.

But you can’t use extends directly on values — that’s where satisfies comes in.

const superAdmin = {
  id: 2,
  role: 'admin',
  accessLevel: 10
} satisfies Admin; // Valid: includes all required fields from Admin

If you omit a required field, TypeScript will show a compile-time error:

const invalidAdmin = {
  id: 2,
  role: 'admin'
} satisfies Admin; // Error: Property 'accessLevel' is missing

So in short:

  • Use extends when you’re defining or combining types.
  • Use satisfies when you’re validating a value against a type at compile time.

They serve different purposes:
extends creates relationships between types,
satisfies checks relationships between values and types.

Using satisfies with Record types

You can use satisfies with Record to validate that an object fits a key-value structure.

const config = {
  theme: 'dark',
  layout: 'grid'
} satisfies Record<string, string>; // All values are strings

If one of the values is the wrong type, TypeScript will catch it:

const invalidConfig = {
  theme: 'dark',
  debug: true
} satisfies Record<string, string>; // Error: boolean is not assignable to string

Using satisfies with object types

Here’s an example where satisfies is used with a custom type, but the object includes extra properties.

type Point = {
  x: number;
  y: number;
};

const origin = {
  x: 0,
  y: 0,
  label: 'origin point' // not part of Point
} satisfies Point; // Valid: has all required fields from Point

You get type safety on required fields, and the extra fields are preserved in the variable’s full type.

Using satisfies with generics

satisfies can be combined with generics such as Record<string, unknown> to enforce shape on dynamic objects.

const data = {
  id: 123,
  isActive: true
} satisfies Record<string, unknown>; // Valid: both values fit 'unknown'

If any value doesn’t match the constraints of the type, TypeScript will warn you.

When to use satisfies in TypeScript

Use satisfies when:

  • You want to validate that a value matches a type at compile time
  • You want to keep extra fields for extended use or flexibility
  • You’re working with configuration, settings, themes, or constant maps
  • You want to preserve literal types for better IntelliSense
  • You care about stronger type checking than what as gives you

Conclusion

The satisfies keyword in TypeScript is a valuable tool for enforcing type correctness without sacrificing extra information or developer experience. Compared to as, it provides safer compile-time validation. And unlike extends, it works directly with values.

Whether you’re validating configuration objects, working with Record types, or building flexible systems with strong type checks, satisfies gives you a modern, precise way to write reliable TypeScript code.

Think about it

If you enjoyed this article, I’d truly appreciate it if you could share it—it really motivates me to keep creating more helpful content!

If you’re interested in exploring more, check out these articles.

Thanks for sticking with me until the end—I hope you found this article valuable and enjoyable!

Want more dev insights like this? Subscribe to get practical tips, tutorials, and tech deep dives delivered to your inbox. No spam, unsubscribe anytime.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top