Напишите type predicate, сужающий значение unknown до User
Обработчик получает разобранный JSON с типом unknown. Реализуйте isUser так, чтобы внутри ветки if (isUser(value)) компилятор сужал value до User.
Ограничения: as не должен утекать наружу из функции, проверка обязана реально изучать значение во время выполнения и должна отвергать null (у которого typeof равен object).
interface User { id: string; email: string; }
function isUser(value: unknown): value is User {
// ваш код здесь
}
Допишите реализацию.
Пользовательский type guard — функция с типом возврата value is User. Когда она возвращает true, компилятор сужает аргумент до User в этой ветке. Тело обязано реально проверять форму в рантайме: предикату доверяют, его не верифицируют.
- ✗Забывать, что
typeof null === 'object', и пропускатьnullчерез проверку - ✗Считать, что компилятор сверяет тело предиката с объявленной формой
- ✗Возвращать
booleanвместоvalue is User, что не даёт никакого сужения
- →Что произойдёт с сужением, если тело предиката проверит не то поле?
- →Как валидатор схемы заменил бы этот написанный вручную guard?
Решение
Type guard — обычная функция; всю работу делает тип возврата value is User. Тело должно проверить форму значения во время выполнения, потому что компилятор его не проверяет.
interface User { id: string; email: string; }
function isUser(value: unknown): value is User {
if (typeof value !== 'object' || value === null) return false; // typeof null === 'object'
const candidate = value as Record<string, unknown>; // as не покидает функцию
return typeof candidate.id === 'string' && typeof candidate.email === 'string';
}
function greet(payload: unknown): string {
if (isUser(payload)) {
return payload.email.toLowerCase(); // payload сужен до User
}
return 'anonymous'; // здесь payload снова unknown
}
⚠️ Предикат — это функция времени выполнения, которой компилятор верит. Если написать return true; или проверить не то поле, TypeScript всё равно сузит значение до User, и падение случится позже, на чужом коде. Это несостоятельность по замыслу: сужение ровно настолько правдиво, насколько правдиво тело.