satisfies solves a tension that annotations can’t: you want TypeScript to check a value against a type, but you don’t want it to forget what it inferred about that value. An annotation does the first and loses the second. satisfies does the first and keeps the second.
// RGB-only Palette
type namedColor = "red" | "green" | "blue";
type RGB = [number, number, number];
type Palette = Record<namedColor, RGB | string>;
// With Annotation
const paletteAnnotated: Palette = {
red: [255, 0, 0],
green: "00ff00",
blue: "0000ff",
};
paletteAnnotated.green.toUpperCase(); // Property 'toUpperCase' does not exist on type 'RGB'.
// With Only Inference
const paletteInferred = {
red: [255, 0, 0],
green: "00ff00",
blueu: [0, 0], // intentional typo AND not a parseable color
};
paletteInferred.green.toUpperCase(); // This now works...
// With `satisfies`!
const paletteSatisfies = {
red: [255, 0, 0],
green: "00ff00",
blue: "0000ff",
} satisfies Palette;
paletteSatisfies.red.map((color) => +color);
paletteSatisfies.green.toUpperCase();
Code language: TypeScript (typescript)