Что такое оператор `satisfies` в TypeScript?
satisfies проверяет, что значение соответствует указанному типу, но при этом сохраняет более точный выведенный тип переменной — в отличие от явной аннотации типа, которая расширяет тип до указанного.Оператор satisfies в TypeScript
Оператор satisfies появился в TypeScript 4.9 и решает классическую проблему: как одновременно получить проверку типа и сохранить точный выведенный тип.
Проблема без satisfies
При явной аннотации типа TypeScript расширяет тип переменной до указанного, теряя точную информацию:
type Colors = 'red' | 'green' | 'blue';
type Palette = Record<Colors, string | [number, number, number]>;
// Явная аннотация — тип каждого значения становится string | [number, number, number]
const palette: Palette = {
red: [255, 0, 0],
green: '#00ff00',
blue: [0, 0, 255],
};
// Ошибка: TypeScript не знает, что red — это массив, а не строка
const redChannel = palette.red.toUpperCase(); // нет ошибки, но упадёт в рантайме
Решение с satisfies
const palette = {
red: [255, 0, 0],
green: '#00ff00',
blue: [0, 0, 255],
} satisfies Palette;
// TypeScript знает точный тип каждого поля
const redChannel = palette.red[0]; // OK — number
const greenUpper = palette.green.toUpperCase(); // OK — string
// Но проверка типа всё равно работает
const wrong = {
red: [255, 0, 0],
green: '#00ff00',
// Ошибка: отсутствует обязательное поле blue
} satisfies Palette;
Ключевые отличия от аннотации типа
Аннотация : Type | satisfies Type | |
|---|---|---|
| Проверка типа | Да | Да |
| Расширение типа | Да | Нет |
| Сохраняет выведенный тип | Нет | Да |
| Влияет на тип переменной | Да | Нет |
Практические сценарии
1. Конфигурационные объекты:
type Config = {
port: number;
host: string;
flags: Record<string, boolean>;
};
const config = {
port: 3000,
host: 'localhost',
flags: { debug: true, verbose: false },
} satisfies Config;
// TypeScript точно знает тип flags.debug — boolean, не unknown
const isDebug: boolean = config.flags.debug;
2. Сужение union-типов в значениях:
type Route = {
path: string;
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
};
const routes = [
{ path: '/users', method: 'GET' },
{ path: '/users', method: 'POST' },
] satisfies Route[];
// method выведен как 'GET' | 'POST', а не просто string
Важный нюанс
satisfies — это операция проверки на этапе компиляции, она не влияет на рантайм-поведение и не генерирует никакого JavaScript-кода. Это чисто статический инструмент TypeScript.
Что хочет услышать интервьюер
Понимание разницы между `satisfies` и явной аннотацией типа — что оба проверяют тип, но аннотация расширяет тип переменной, а `satisfies` сохраняет точный выведенный тип
Знание версии появления оператора (TypeScript 4.9) и базового синтаксиса
Умение объяснить практический кейс: конфигурационные объекты, словари с union-типами в значениях
Понимание того, что `satisfies` не генерирует код в рантайме — это только компиляторная проверка
Способность привести пример, где `satisfies` решает реальную проблему потери типа при явной аннотации
Пример: Сравнение аннотации типа и satisfies
type Theme = {
primary: string | [number, number, number];
secondary: string | [number, number, number];
};
// С аннотацией — тип расширяется
const themeAnnotated: Theme = {
primary: '#ff0000',
secondary: [0, 128, 255],
};
// themeAnnotated.primary — string | [number, number, number]
// .toUpperCase() вызовет ошибку TS, хотя значение — строка
// С satisfies — тип сохраняется точным
const themeSatisfies = {
primary: '#ff0000',
secondary: [0, 128, 255],
} satisfies Theme;
// themeSatisfies.primary — string (точный тип!)
const upper = themeSatisfies.primary.toUpperCase(); // OK
// themeSatisfies.secondary — [number, number, number] (точный тип!)
const blue = themeSatisfies.secondary[2]; // OK — number
Пример: Реальный кейс: конфигурация приложения
type AppConfig = {
env: 'development' | 'production' | 'test';
port: number;
database: {
host: string;
port: number;
};
};
// satisfies гарантирует соответствие AppConfig,
// но сохраняет литеральный тип 'development'
const config = {
env: 'development',
port: 3000,
database: {
host: 'localhost',
port: 5432,
},
} satisfies AppConfig;
// config.env выведен как 'development', а не string
const isDev = config.env === 'development'; // TS знает, что это true
// Ошибка компиляции — отсутствует поле database
const badConfig = {
env: 'production',
port: 8080,
} satisfies AppConfig; // Property 'database' is missing
Типичные ошибки
Путают `satisfies` с аннотацией типа — считают, что это синонимы и не понимают разницы в поведении вывода типов
Думают, что `satisfies` изменяет тип переменной, хотя она остаётся с точным выведенным типом
Не знают версию TypeScript, в которой появился оператор, и не могут сказать, что он относительно новый
Не понимают, что `satisfies` ничего не делает в рантайме — ошибочно считают его runtime-валидатором
Не могут привести практический пример и объясняют оператор только абстрактно


