satisfies vs Type Annotation in TypeScript โ What's the Difference?
๐ฆ What is satisfies
?
The satisfies
operator validates that a value conforms to a given type โ without changing the inferred type of the variable.
1const roles = ["admin", "user", "guest"] satisfies string[]; 2
This ensures that:
-
roles is an array of strings
-
But its actual type is still: ("admin" | "user" | "guest")[] โ not just string[]
โ Why that matters:
1if (roles.includes("superadmin")) { 2 // โ TypeScript will catch this โ "superadmin" not allowed 3} 4
You get both type checking and value precision.
๐ฆ What does :
do?
Type annotations like : string[]
or : MyType
force TypeScript to treat the value as that type โ even if it could be narrower.
1const roles: string[] = ["admin", "user", "guest"]; 2
Now the array is just string[]. Youโve lost the literal types ("admin", etc.). TypeScript assumes it could contain "anything" as long as it's a string.
โ ๏ธ Problem:
1roles.includes("superadmin"); // โ No error โ TypeScript allows it 2
You lose safety because "superadmin" is a valid string.
๐งช Real Example: Status Mapping
1const SUCCESS_STATUSES = [ 2 "completed", 3 "reversed", 4] satisfies TransactionStatus[]; 5 6function addStatus(status: TransactionStatus) { 7 return SUCCESS_STATUSES.push(status); // โ safe, type-narrowed 8} 9
Now try with a type annotation:
1const SUCCESS_STATUSES: TransactionStatus[] = ["completed", "reversed"]; 2 3function addStatus(status: TransactionStatus) { 4 return SUCCESS_STATUSES.push(status); // โ might allow invalid values 5} 6
Summary
Comparison
Feature | Type Annotation | satisfies Operator |
---|---|---|
Checks type correctness | โ Yes | โ Yes |
Narrows literal values | โ No (widens) | โ Yes (keeps specificity) |
Controls variable type | โ Sets the final type | โ Keeps inferred (narrow) type |
Safer includes() checks | โ Less accurate | โ More accurate |
When to use?
Situation | Use satisfies | Use : (type annotation) |
---|---|---|
Constant lists (roles, statuses) | โ Narrowed, safe, expressive | โ Will lose literal values |
includes() or .has() logic | โ Safer and type-checked | โ May allow unsafe values |
Variable needs to be general | โ satisfies is too strict | โ Type annotation fits better |
Object conformance without widening | โ Keeps inferred shape | โ Annotation might override shape |