Проверка типа интерфейса в TypeScript: как определить соответствие объекта интерфейсу?
Проблема: интерфейсы TypeScript существуют только в compile-time
Интерфейсы TypeScript не имеют представления в рантайме — они полностью стираются при компиляции в JavaScript. Поэтому вы не можете использовать instanceof или typeof для проверки соответствия интерфейсу. Решение — написать пользовательскую функцию-проверку (type guard), которая выполняет ручную валидацию структуры объекта.
Решение: пользовательский type guard с is-предикатом
Создайте функцию, которая принимает unknown и возвращает obj is User. Внутри проверьте каждое поле:
interface User {
name: string;
age: number;
email: string;
}
function isUser(obj: unknown): obj is User {
if (!obj || typeof obj !== 'object') return false;
const user = obj as Record<string, unknown>;
return (
typeof user.name === 'string' &&
typeof user.age === 'number' &&
typeof user.email === 'string'
);
}
// Использование:
const data: unknown = JSON.parse('{"name":"Alice","age":30,"email":"alice@example.com"}');
if (isUser(data)) {
// TypeScript знает, что data — User
console.log(data.name.toUpperCase()); // OK
}
Расширенный подход: использование библиотеки для валидации
Если у вас много интерфейсов, ручное написание проверок становится утомительным. Используйте библиотеку zod или io-ts. Пример с zod:
import { z } from 'zod';
const UserSchema = z.object({
name: z.string(),
age: z.number(),
email: z.string().email(),
});
type User = z.infer<typeof UserSchema>;
// Проверка:
const result = UserSchema.safeParse(data);
if (result.success) {
const user: User = result.data; // строго типизирован
} else {
console.error(result.error);
}
Важные моменты
- Проверка на null/undefined: всегда начинайте с
if (!obj || typeof obj !== 'object'). - Глубокие объекты: для вложенных структур рекурсивно проверяйте каждое поле.
- Необязательные поля: используйте
if (field !== undefined && typeof field !== ...). - Производительность: для больших данных рассмотрите схемы валидации (zod, ajv).
Этот подход гарантирует безопасность на этапе компиляции и в рантайме. TypeScript не будет ругаться, а если данные придут с ошибкой — вы получите понятное сообщение.
<<Альтернатива: использование класса с instanceof
Если вы не хотите писать сложные проверки вручную, можно заменить интерфейс на класс. У классов есть представление в рантайме, и можно использовать instanceof:
class User {
constructor(
public name: string,
public age: number,
public email: string
) {}
}
function parseUser(obj: unknown): User | null {
if (!obj || typeof obj !== 'object') return null;
const { name, age, email } = obj as any;
if (typeof name === 'string' && typeof age === 'number' && typeof email === 'string') {
return new User(name, age, email);
}
return null;
}
const data = JSON.parse('{"name":"Bob","age":25,"email":"bob@test.com"}');
const user = parseUser(data);
if (user instanceof User) {
console.log(user.name); // безопасно
}
Недостатки:
- Классы сложнее интерфейсов (нужно писать конструктор).
- Потеря структурной типизации — классы номинативны.
- Для JSON-данных всё равно нужна ручная проверка полей.
Этот подход подходит, если вы контролируете создание объектов и хотите использовать instanceof для проверки типа в рантайме. Для чистых данных из API лучше использовать первый вариант с type guard или библиотеку валидации.
Ответов пока нет.
Войдите чтобы оставить ответ