The satisfies keyword was Introduced in TypeScript 4.9 and is an operator that checks if a value meets a specific type. It’s useful for checking that a values follows a certain type, and keeps the exact value’s type information.
Imagine in some weird universe we have two ways of authenticating a user, and we want to represent the result of that authentication in TypeScript. This type is either a bearer token from an Authorization header, or it’s an object with a username and password.
You can create a union type like this:
type AuthorizationHeader = string;
type AuthorizationObject = { username: string, password: string};
type Authorization = AuthorizationHeader | AuthorizationObject;
Normally, you might use as or : type to tell TypeScript, “Hey, trust me—this fits the type!” But those can sometimes lose details about the value.
const token = 'Bearer eyJhbGciI***fQ' as Authorization
The TypeScript compiler does not know that token matches the string type. When using the as operator, we’re losing the primitive type. In the above case we cannot do token.startsWith('Bearer') because the startsWith method is part of String. But token is of type Authorization which is an union type of AuthorizationHeader & AuthorizationObject
We can fix this using the satisfies keyword
const token = 'Bearer eyJhbGciI***fQ' satisfies Authorization;
const authentication = {
username: "ken",
password: "***",
} satisfies Authorization;
Why is this cool?
- Type Checking: It ensures the token is a valid string and the authentication object fits the object shape. If you mess up the structure, TypeScript will complain and be very disappointed in you.
- Keeps Value Details: With satisfies, TypeScript remembers the exact properties and values of the object instead of treating it as just a generic Authorization.
Why you should not use the as keyword?
const faultyToken = {username: 'whoops'} as Authorization;
The TypeScript compiler will not complain or yell in the above example. You’re telling TypeScript “I am smarter than you, this is a variable of type Authorization.”
Here comes Satisfies 😏
const unsatisfiedToken = {username: 'whoops'} satisfies Authorization;
const satisfiedToken = {username: 'whoops', password: "***"} satisfies Authorization;
The unsatisfiedToken will trigger the following TypeScript error:
Type ‘{ username: string; }’ does not satisfy the expected type ‘Authorization’.
Property ‘password’ is missing in type ‘{ username: string; }’ but required in type ‘AuthorizationObject’.
When to Use satisfies?
- When you need to check that a value fits a type without losing its specific shape.
- If you want to keep the exact structure for better autocompletion and future checks.
- When you want to catch mistakes early while still allowing flexibility between different types.