- Abstract class
- Annotations
- Array
- Asserts
- Casting
- Class
- Conditional types
- Const
- Date object
- Decorators
- Default parameter
- Dictionary
- Enum
- Exclude type
- Extract type
- For loop
- forEach()
- Function
- Generics
- Index signature
- Infer
- Inheritance
- Interface
- Keyof type operator
- Let
- Map type
- Mixin
- Module
- Namespace
- Never
- Object type
- Omit type
- Operator
- Optional parameter
- Partial type
- Pick type
- Promise
- Property
- Readonly type
- Record type
- Required type
- Satisfies operator
- Tuples
- Type alias
- Type assertion
- Type guard
- Type narrowing
- Typeof Type Operator
- Union
- Utility types
- Var
- Void
TYPESCRIPT
TypeScript satisfies
Operator: Purpose, Usage, and Examples
The satisfies
operator, introduced in TypeScript 4.9, lets you check that a value conforms to a particular type without changing its inferred structure. This means you get the benefits of structural type validation without losing the narrow type information that TypeScript infers from the original value.
Instead of forcing a value into a new type, the satisfies
operator validates that the value matches the expected shape while keeping its most precise, specific type.
What Is the satisfies
Operator?
The satisfies
operator ensures that an expression is assignable to a given type, without modifying or transforming it.
Syntax:
const variable = expression satisfies TargetType;
Here, TypeScript checks that expression
matches TargetType
, but infers the type of variable
directly from the expression, not from the target type.
Preserving Narrow Types
One of the biggest advantages of using satisfies
is that it retains literal types, enabling more specific and accurate type behavior.
const directions = ["north", "south", "east", "west"] as const;
const obj = {
north: "up",
south: "down",
east: "right",
west: "left",
} satisfies Record<(typeof directions)[number], string>;
In this example, TypeScript checks that the object covers all required keys but preserves the literal types of each value.
Validating Object Structures
The operator helps ensure that an object correctly conforms to an interface or type definition.
type User = {
id: number;
name: string;
};
const user = {
id: 1,
name: "Alice",
} satisfies User;
If you omit or mistype a property, TypeScript will issue an error during compilation.
Ensuring Complete Mappings
You can validate full key coverage when working with maps or configuration objects.
const statuses = {
idle: "Idle",
loading: "Loading",
success: "Success",
error: "Error",
} satisfies Record<"idle" | "loading" | "success" | "error", string>;
This guarantees that all required keys are included—no more, no less.
Using with as const
The as const
assertion freezes values to their literal types. Combining it with satisfies
gives you both structural validation and type specificity.
const theme = {
light: "#FFF",
dark: "#000",
} as const satisfies Record<string, string>;
This approach keeps "light"
and "dark"
as literal values while ensuring they’re valid strings in a broader context.
Array and Tuple Validation
Satisfies
also works well when mapping values from fixed arrays or tuples.
const roles = ["admin", "user", "guest"] as const;
const permissions = {
admin: true,
user: true,
guest: false,
} satisfies Record<(typeof roles)[number], boolean>;
This ensures that every role has a defined permission and avoids accidental omissions.
Difference from Type Assertions
Unlike type assertions (e.g., as Type
), satisfies
doesn’t silence type errors. Instead, it verifies correctness without overriding the inferred type.
const invalid = { x: 1 } as { x: number; y: number }; // No error
const validated = { x: 1 } satisfies { x: number; y: number }; // Error: 'y' is missing
This helps prevent logical errors that could be introduced by overconfident casting.
Difference from Type Annotations
Annotations like const obj: Type = value
force the compiler to adopt the annotated type, often widening literal values. In contrast, satisfies
keeps the original narrow values intact.
const label = {
status: "active",
} satisfies { status: string }; // status is still "active"
const typed: { status: string } = {
status: "active",
}; // status is now widened to string
Preserving narrow values helps with strict equality checks and discriminated unions.
Validating Config Objects
Developers often use satisfies
when creating configuration files or static definitions to ensure the data structure is safe.
const config = {
baseUrl: "https://api.example.com",
retry: 3,
} satisfies {
baseUrl: string;
retry: number;
};
This avoids over-annotation while ensuring that the config meets required constraints.
Mapping Enum Keys
Pairing enums with value maps is a common pattern, and satisfies
ensures consistency between enum values and keys.
enum Status {
Open = "open",
Closed = "closed",
}
const messages = {
open: "Case is open",
closed: "Case is closed",
} satisfies Record<Status, string>;
This ensures your mapping is complete and accurately typed, which is especially useful in apps with multiple UI states or translations.
Why Use satisfies
?
- Keeps literal values intact — useful for narrowing types without widening.
- Improves developer experience — better autocompletion and more helpful compiler errors.
- Reduces unnecessary verbosity — avoids extra type annotations that obscure intent.
- Boosts reliability in static config — catch shape mismatches at compile time.
- Integrates well with
as const
— enables expressive and safe type modeling.
Limitations
Despite its usefulness, the satisfies
operator has a few constraints:
- Only works at compile time — it doesn’t affect how the code behaves at runtime.
- Not usable in expressions — you can only use it in declarations.
- Doesn’t narrow types at runtime — still need type guards for runtime validation.
- Requires clear shape — won’t infer types through complex logic or side effects.
Best Practices
- Combine with
as const
to keep both structure and literal precision. - Use it instead of assertions or annotations for validating static data.
- Apply it in map objects, enums, or static configurations to catch errors early.
- Don’t use it for values that require runtime validation or transformation.
Summary
The satisfies
operator adds another layer of type safety to TypeScript by confirming structural compatibility without discarding inferred details. It helps you build safer configurations, enforce object structures, and validate mappings—all without resorting to type assertions or verbose annotations.
By adopting this operator in projects with strict typing needs or static data structures, you can maintain high code quality while benefiting from smarter, more expressive type inference.
Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.