Новое:Talanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

+1 393новые вакансии за сутки·54 487вакансий открыто сейчас·Новое:Talanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

Новые вакансии в TelegramРаботодателям
Talanto
Вакансии
Компании5 590
РезюмеAIПодготовкаСтатьи
BoostТарифыBoost
Войти

Не нашли подходящее?

Пусть нужная вакансия найдёт вас сама.

  1. Подборка в TelegramНовые вакансии по вашему фильтру — сразу в бота.Подключить
  2. Мэтчи по резюмеЗагрузите резюме — покажем, где вы подходите лучше всего.Загрузить
  3. Сохранить фильтрНастройте поиск один раз и возвращайтесь к новым вакансиям.Настроить
Что нового на TalantoTalanto осенью: поиск с цифрами, вакансия по шагам и каталог компаний

Для работодателей

Опубликуйте вакансию — отклики придут в ваш кабинет.

  1. Вакансиябесплатно
  2. Откликиконтакты бесплатно
  3. Наймэтапы и интервью

40 компаний публикуют вакансии напрямую · 4 396 кандидатов открыты к предложениям

Разместить вакансию

Популярные направления

Все подборки
  • Python8 807
  • Облачные технологии6 651
  • QA вакансии2 171
  • Android1 317
  • Инженер данных867
  • Продакт-менеджер313

Разработка

  • iOS1 229
  • Backend вакансии1 199
  • AI вакансии548
  • Fullstack вакансии496
  • Frontend вакансии424
  • Mobile вакансии28

По стеку

  • Go5 239
  • Java3 132
  • Kotlin1 122
  • Node.js1 007
  • Rust852
  • .NET662
  • PHP319
  • C++268
  • C#207

DevOps и инфраструктура

  • Kubernetes3 912
  • Linux-инфраструктура2 845
  • DevOps вакансии2 680
  • Terraform / IaC2 177
  • Мониторинг и Observability1 072
  • CI/CD913
  • SRE307
  • Кибербезопасность34

Аналитика и данные

  • Аналитик данных528
  • Data Scientist433
  • Бизнес-аналитик399
  • Системный аналитик67

Другие направления

  • Проджект-менеджер105
  • UI/UX дизайн68
  • Ручное тестирование14

По регионам

  • Вакансии в США25 774
  • Вакансии в Европе10 284
  • Работа в России3 616
  • Вакансии в Канаде2 260

По формату

  • Удалённые вакансии42 533
  • Релокация в США25 774
  • Гибридная работа5 661
  • Офисная работа4 440

По уровню

  • Senior вакансии22 599
  • Middle вакансии11 490
  • Junior вакансии3 852

Сейчас нанимают

Все компании
  • Rakuten189 вакансий
  • Wise187 вакансий
  • ASML164 вакансии
  • Grab134 вакансии
  • Celonis47 вакансий
  • Spotify37 вакансий
  • Infobip28 вакансий
  • Adyen27 вакансий
  • Monzo19 вакансий
  • Darktrace17 вакансий

Вакансии из 344 источников: карьерные страницы компаний и джоб-борды.

КомпанииО насНовостиПубличная офертаУсловия использованияПолитика конфиденциальностиПоддержка
←К теме TypeScriptВсе вопросы
TypeScriptSeniorТеория

Как сделать тип рекурсивным в TypeScript? Приведите пример.

В закладки
Сначала попробуйте ответить сами30 секунд
Сравнить с ответом ↓

Рекурсивный тип ссылается на себя в собственном определении: type JsonValue = string | number | JsonValue[] | { [k: string]: JsonValue }. Используйте interface для структур данных (ленивое вычисление) и type для mapped/conditional рекурсивных утилит.

Базовый пример — JSON Value

type JsonPrimitive = string | number | boolean | null;

type JsonValue =
  | JsonPrimitive
  | JsonValue[]          // массив JSON-значений
  | { [key: string]: JsonValue }; // объект с JSON-значениями

// Использование:
const data: JsonValue = {
  name: 'Alice',
  scores: [1, 2, 3],
  meta: { active: true, tags: ['a', 'b'] },
};

Рекурсивные типы в TypeScript

TypeScript поддерживает рекурсивные типы: тип может ссылаться на самого себя при определении. Это позволяет описывать вложенные структуры произвольной глубины — деревья, JSON, вложенные меню, AST и т.д.

Дерево узлов

interface TreeNode<T> {
  value: T;
  children?: TreeNode<T>[];
}

const tree: TreeNode<string> = {
  value: 'root',
  children: [
    { value: 'child1' },
    {
      value: 'child2',
      children: [
        { value: 'grandchild' },
      ],
    },
  ],
};

function mapTree<T, U>(node: TreeNode<T>, fn: (v: T) => U): TreeNode<U> {
  return {
    value: fn(node.value),
    children: node.children?.map((c) => mapTree(c, fn)),
  };
}

DeepPartial — рекурсивный утилитный тип

type DeepPartial<T> = T extends object
  ? { [K in keyof T]?: DeepPartial<T[K]> }
  : T;

interface Config {
  server: {
    host: string;
    port: number;
    tls: { cert: string; key: string };
  };
  debug: boolean;
}

type PartialConfig = DeepPartial<Config>;

const patch: PartialConfig = {
  server: { port: 443 }, // остальные поля опциональны
};

DeepReadonly

type DeepReadonly<T> = T extends (infer U)[]
  ? ReadonlyArray<DeepReadonly<U>>
  : T extends object
  ? { readonly [K in keyof T]: DeepReadonly<T[K]> }
  : T;

Рекурсивные условные типы (TS 4.1+)

// Путь в объекте через точку: 'a.b.c'
type Paths<T> = T extends object
  ? {
      [K in keyof T & string]:
        | K
        | `${K}.${Paths<T[K]> & string}`;
    }[keyof T & string]
  : never;

interface Form {
  user: { name: string; age: number };
  active: boolean;
}

type FormPaths = Paths<Form>;
// 'user' | 'user.name' | 'user.age' | 'active'

Ограничения компилятора

TypeScript ограничивает глубину рекурсии. При слишком глубоких типах выдаётся: Type instantiation is excessively deep and possibly infinite. Обычный предел — около 50 уровней для дистрибутивных условных типов.

// Обходной путь через интерфейс (lazy evaluation)
// Интерфейсы вычисляются лениво, в отличие от type aliases
interface NestedArray<T> extends Array<T | NestedArray<T>> {}

// Вместо:
type NestedArray<T> = T | NestedArray<T>[]; // может вызвать бесконечный цикл

Подводные камни

  • Type instantiation is excessively deep — компилятор имеет жёсткий лимит рекурсии; при его достижении нужно переписать тип через интерфейс или упростить логику.
  • type alias vs interface для рекурсии — type вычисляется жадно, interface — лениво. Для рекурсивных структур данных предпочтительнее interface; для рекурсивных mapped types — type.
  • DeepPartial с массивами — по умолчанию DeepPartial<T[]> даёт DeepPartial<T>[], что редко нужно; часто массивы нужно обрабатывать отдельно.
  • Циклические зависимости типов — тип не может ссылаться на самого себя через type X = X; нужна хотя бы одна условная ветка или обёртка.
  • Производительность компилятора — глубокие рекурсивные типы резко замедляют tsc и языковой сервер; следите за временем проверки через --diagnostics.
  • Потеря точности в union-распределении — когда T в условном типе является union, TypeScript распределяет рекурсию по каждому члену, что может экспоненциально увеличить количество вычислений.
  • Глубина стека в runtime — рекурсивный тип красив в compile-time, но рекурсивная runtime-функция (mapTree, deepClone) тоже должна обрабатывать чрезмерную вложенность через явный лимит глубины или итеративный подход.
  • infer в рекурсивных типах — при использовании infer внутри рекурсии легко получить непредсказуемые результаты; тестируйте граничные случаи через type Test = Expect<Equal<...>>.

Частые вопросы на собеседовании

  • Что такое TypeScript и какие основные преимущества он даёт по сравнению с обычным JavaScript?
  • В чём разница между interface и псевдонимом типа (type) в TypeScript?
  • Что такое generics в TypeScript и зачем они нужны? Приведите пример.
  • Для каких задач TypeScript является сильным выбором, а где лучше честно выбрать другой язык?

Типичные ошибки

  • Смешивать «рекурсивные типы» с похожим механизмом без критерия выбора.
  • Игнорировать риск: неверно оценить границы применения темы «рекурсивные типы» и получить хрупкое решение.
  • Показывать только синтаксис и не объяснять поведение в runtime или сборке.

Что проверяет интервьюер

  • Объясняет описание деревьев, JSON и вложенных структур.
  • Показывает на примере, как работает: рекурсивный тип ссылается на себя через свойства или union; важно добавить базовый случай, иначе тип становится тяжелым для компилятора и непонятным для API.
  • Называет production-нюанс и граничный случай для темы «рекурсивные типы».

Как вы знаете этот вопрос?

Проверить себя по теме TypeScript →

Источники

  • https://www.typescriptlang.org/docs/handbook/2/everyday-types.html
  • https://www.typescriptlang.org/docs/handbook/2/objects.html
←Предыдущий вопросЧто такое `NoInfer<T>` (TypeScript 5.4) и какую проблему он решает?

Связанные темы

TypeScriptapi-contractstype-modeling