๐—ง๐˜†๐—ฝ๐—ฒ๐—ฆ๐—ฐ๐—ฟ๐—ถ๐—ฝ๐˜ ๐—ฆ๐—ฎ๐˜๐—ถ๐˜€๐—ณ๐—ถ๐—ฒ๐˜€ ๐—ข๐—ฝ๐—ฒ๐—ฟ๐—ฎ๐˜๐—ผ๐—ฟ: ๐—ฆ๐˜๐—ผ๐—ฝ ๐—Ÿ๐—ผ๐˜€๐—ถ๐—ป๐—ด ๐—ฌ๐—ผ๐˜‚๐—ฟ ๐—ง๐˜†๐—ฝ๐—ฒ๐˜€

Do you use type annotations for objects? You might be losing valuable data.

When you define an object with a type annotation, TypeScript widens your types.

If you define a route: const routes: Record<string, RouteConfig> = { "/dashboard": { path: "/dashboard", auth: true } };

TypeScript sees "auth" as a boolean. It forgets that it is specifically "true". You lose the narrow literal types you need for strict logic.

You have two bad options before TypeScript 4.9:

  1. No annotation: You get narrow types, but you lose validation. If you make a typo in a property name, TypeScript stays silent. You only find the error at runtime.

  2. Type assertion (using "as"): You tell TypeScript to trust you. This suppresses errors. If you miss a required field or make a typo, TypeScript will not warn you. You lose safety and narrow types at the same time.

The Solution: The satisfies operator.

The satisfies operator validates your object without changing its inferred type. It gives you the best of both worlds: validation and narrow types.

Why it works:

Real world examples:

โ€ข Theme objects: Keep your specific color names instead of widening everything to a general string. This keeps your autocomplete working perfectly.

โ€ข Status maps: Ensure every status color is valid. If you use "gray" instead of "red" or "green," TypeScript catches it immediately.

โ€ข Event handlers: Ensure every function in a map follows the same signature while keeping the unique argument types for each specific handler.

When to use each method:

Stop choosing between safety and precision. Use satisfies to get both.

Source: https://dev.to/kaithorne/typescripts-satisfies-operator-when-as-lets-you-down-and-annotations-strip-your-types-2okg