TypeScript на всех фронтах: как писать код для web, mobile и desktop

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

TypeScript — универсальный солдат современной разработки

Вы когда-нибудь мечтали написать одну кодовую базу и запустить её на сайте, в мобильном приложении и на десктопе? Лет десять назад это звучало бы как фантастика. Сегодня TypeScript даёт нам такую возможность без магии и жертв.

TypeScript — это не просто «JavaScript с типами». Это мощный инструмент, который превращает хаос динамической типизации в стройную архитектуру. А главное — он одинаково хорошо ложится на любую платформу. Веб, мобильные устройства (iOS, Android) и настольные системы (Windows, macOS, Linux) — везде есть свой TypeScript-фреймворк.

В этой статье мы разберём реальные стратегии и примеры кода, которые помогут вам стать настоящим кроссплатформенным разработчиком на TypeScript. Вы узнаете, как избежать дублирования логики, какие библиотеки выбрать и как не потерять производительность.

Почему TypeScript стал стандартом для кроссплатформенной разработки

Раньше для каждой платформы приходилось учить новый язык: Swift для iOS, Java/Kotlin для Android, C# для Windows, Python для бэкенда. TypeScript ломает этот стереотип. Он работает везде, где есть JavaScript-рантайм (браузер, Node.js, Deno) или нативная обёртка (React Native, Electron).

Основные преимущества TypeScript в кроссплатформенной разработке:

  • Единая кодовая база — пишете бизнес-логику один раз, используете на всех платформах.
  • Строгая типизация — отлавливаете баги на этапе компиляции, а не в рантайме.
  • Богатая экосистема — тысячи библиотек с готовыми типами (DefinitelyTyped).
  • Современный синтаксис — async/await, дженерики, декораторы, утилитарные типы.

Кстати, если вы уже работаете с Python и хотите попробовать TypeScript, то вас ждёт приятный сюрприз: многие концепции (статическая типизация, интерфейсы, дженерики) очень похожи. На pythonlib.ru мы любим показывать, как разные языки решают одни и те же задачи. TypeScript в этом смысле — идеальный мост между вебом и нативом.

Архитектура кроссплатформенного проекта на TypeScript

Чтобы код работал везде, нужно разделить приложение на три слоя:

  • Ядро (Core) — чистая бизнес-логика, не зависящая от платформы.
  • Адаптеры (Adapters) — тонкие прослойки для UI, файловой системы, сети.
  • Платформенные обёртки — React для веба, React Native для мобилок, Electron для десктопа.

Рассмотрим пример: приложение для заметок с тегами. Ядро будет содержать только типы и функции работы с данными.

// core/types.ts
export interface Note {
  id: string;
  title: string;
  content: string;
  tags: string[];
  createdAt: Date;
}

// core/noteService.ts
export function filterNotesByTag(notes: Note[], tag: string): Note[] {
  return notes.filter(note => note.tags.includes(tag));
}

export function createNote(title: string, content: string, tags: string[]): Note {
  return {
    id: crypto.randomUUID(),
    title,
    content,
    tags,
    createdAt: new Date(),
  };
}

Этот код можно использовать в любом окружении. Никаких зависимостей от DOM, React или Node.js. Чистая TypeScript-логика.

Кроссплатформенный UI: React + React Native + Electron

Самый популярный стек для кроссплатформенной разработки на TypeScript — это React (веб), React Native (мобильные) и Electron (десктоп). Все три используют один синтаксис компонентов, но с разными рендерерами.

Шаг 1. Создаём общие компоненты

Можно вынести логику отображения в абстрактные компоненты, которые будут использовать платформенные примитивы.

// shared/NoteCard.tsx
import { View, Text, StyleSheet } from 'react-native'; // для React Native
// import { View, Text, StyleSheet } from 'react-native-web'; // для веба

interface NoteCardProps {
  title: string;
  preview: string;
  onPress: () => void;
}

export const NoteCard: React.FC<NoteCardProps> = ({ title, preview, onPress }) => {
  return (
    <View style={styles.card} onClick={onPress}>
      <Text style={styles.title}>{title}</Text>
      <Text style={styles.preview}>{preview}</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  card: {
    padding: 16,
    margin: 8,
    backgroundColor: '#fff',
    borderRadius: 8,
    shadowColor: '#000',
    shadowOpacity: 0.1,
    shadowRadius: 4,
  },
  title: {
    fontSize: 18,
    fontWeight: 'bold',
  },
  preview: {
    fontSize: 14,
    color: '#666',
  },
});

Обратите внимание: onClick в вебе — это onPress в React Native. Но TypeScript позволяет использовать условные типы, чтобы сделать API единым.

Шаг 2. Платформенные адаптеры

Для работы с хранилищем данных создадим интерфейс и две реализации.

// core/storage.ts
export interface IStorage {
  getNotes(): Promise<Note[]>;
  saveNotes(notes: Note[]): Promise<void>;
}

// web/storage.ts (LocalStorage)
export class WebStorage implements IStorage {
  async getNotes(): Promise<Note[]> {
    const data = localStorage.getItem('notes');
    return data ? JSON.parse(data) : [];
  }

  async saveNotes(notes: Note[]): Promise<void> {
    localStorage.setItem('notes', JSON.stringify(notes));
  }
}

// native/storage.ts (AsyncStorage для React Native)
import AsyncStorage from '@react-native-async-storage/async-storage';

export class NativeStorage implements IStorage {
  async getNotes(): Promise<Note[]> {
    const data = await AsyncStorage.getItem('notes');
    return data ? JSON.parse(data) : [];
  }

  async saveNotes(notes: Note[]): Promise<void> {
    await AsyncStorage.setItem('notes', JSON.stringify(notes));
  }
}

// desktop/storage.ts (fs для Electron)
import { app } from 'electron';
import * as fs from 'fs';
import * as path from 'path';

export class DesktopStorage implements IStorage {
  private filePath = path.join(app.getPath('userData'), 'notes.json');

  async getNotes(): Promise<Note[]> {
    if (!fs.existsSync(this.filePath)) return [];
    const data = fs.readFileSync(this.filePath, 'utf-8');
    return JSON.parse(data);
  }

  async saveNotes(notes: Note[]): Promise<void> {
    fs.writeFileSync(this.filePath, JSON.stringify(notes), 'utf-8');
  }
}

Теперь в главном файле приложения мы просто подставляем нужную реализацию в зависимости от платформы:

// app.ts
import { WebStorage }                

Блоги

Рекомендаций по книгам