Skip to content

Справочник API ​

Текущая ОС ​

getOS() — возвращает одну строку, идентифицирующую текущую операционную систему.

ts
import { getOS } from 'os-detect'

const os = getOS()
// 'ios' | 'macos' | 'android' | 'windows' | 'linux' | 'chromeos' | 'unknown'

Приоритет определения (побеждает первое совпадение):

  1. iOS / iPadOS
  2. Android
  3. ChromeOS
  4. Linux
  5. macOS
  6. Windows
  7. 'unknown'

ChromeOS проверяется раньше Linux, потому что userAgent-строки ChromeOS содержат "Linux" — неправильный порядок проверки привёл бы к тому, что Chromebook определялся бы неверно.

Тип OS ​

ts
type OS = 'ios' | 'macos' | 'android' | 'windows' | 'linux' | 'chromeos' | 'unknown'

Булевы проверки ​

Все функции ниже синхронны, не имеют побочных эффектов и кэшируют свой результат после первого вызова.

ts
import {
  detectIsIOS,
  detectIsMacOS,
  detectIsAndroid,
  detectIsWindows,
  detectIsLinux,
  detectIsChromeOS,
} from 'os-detect'

detectIsIOS() ​

boolean

true для iPhone, iPod или iPad (включая iPadOS 13+). В Node.js всегда false — не определяется на сервере.

detectIsMacOS() ​

boolean

true для macOS-десктопа (корректно исключает iPadOS 13+). В Node.js: process.platform === 'darwin'.

detectIsAndroid() ​

boolean

true для телефонов и планшетов Android. В Node.js: process.platform === 'android'.

detectIsWindows() ​

boolean

true для Windows-десктопа или ноутбука (32-битный и 64-битный). В Node.js: process.platform === 'win32'.

detectIsLinux() ​

boolean

true для Linux-десктопа (исключает Android и ChromeOS). В Node.js: process.platform === 'linux'.

detectIsChromeOS() ​

boolean

true для устройств ChromeOS. В Node.js всегда false — не определяется на сервере.

Особенность iPadOS 13+ ​

Начиная с iPadOS 13, Safari сообщает Macintosh в строке userAgent. detectIsIOS() корректно обрабатывает это, проверяя navigator.maxTouchPoints > 1. detectIsMacOS() соответственно исключает устройства на iPadOS — вы никогда не получите true от обеих функций на одном устройстве.

Пример — условный рендеринг ​

ts
import { detectIsIOS, detectIsAndroid, detectIsWindows } from 'os-detect'

if (detectIsIOS()) {
  // показать бейдж App Store
} else if (detectIsAndroid()) {
  // показать бейдж Google Play
} else if (detectIsWindows()) {
  // показать бейдж Windows Store
}

Определение Windows 11 ​

detectIsWindows11()

Promise<boolean>

true только тогда, когда detectIsWindows() равно true и проверка Windows 11 прошла успешно.

ts
import { detectIsWindows11 } from 'os-detect'

const isWin11 = await detectIsWindows11()

Браузер — использует navigator.userAgentData.getHighEntropyValues(['platformVersion']) (Chrome 90+ / Edge 90+). Windows 11 сообщает platformVersion >= 13.0.0. Возвращает false, если API недоступен или вызов не удался.

Node.js — использует os.release(). У Windows 11 номер сборки >= 22000. Возвращает false, если импорт не удался.

Немедленно возвращает false, если detectIsWindows() равно false — асинхронная работа не выполняется. Как и все булевы детекторы, результат кэшируется после первого вызова; параллельные вызовы, сделанные до его разрешения, используют один и тот же промис вместо того, чтобы каждый запускал свою проверку. Чтобы принудительно перезапустить проверку, вызовите resetDetectionCache().

ts
// Различаем Windows 10 и Windows 11
const isWindows = detectIsWindows()
const isWin11 = await detectIsWindows11()

if (isWin11) {
  console.log('Windows 11')
} else if (isWindows) {
  console.log('Windows 10 или старше')
}

Сброс кэша ​

resetDetectionCache()

void

Очищает все кэшированные результаты определения — все функции detectIs*(), getOS() и detectIsWindows11() заново выполнят проверку при следующем вызове. Также сбрасывает флаг предупреждения об устаревании detectIsiOS(), поэтому следующий вызов этого алиаса снова выведет console.warn.

ts
import { resetDetectionCache } from 'os-detect'

resetDetectionCache() // очищает все кэшированные результаты определения

В обычной вкладке браузера ОС никогда не меняется в течение сессии, поэтому обычно это не нужно. Функция существует для продвинутых случаев:

  • Долгоживущий процесс Node.js (например, главный процесс Electron), которому нужно переоценить process.platform после смены контекста.
  • Тестовые наборы, которые мокают navigator/process.platform в каждом тесте без повторного импорта модуля.

Устаревший алиас ​

detectIsiOS()

boolean · идентична detectIsIOS()

Устарела — переименована в detectIsIOS() (заглавная OS) для согласованности с остальным API в v2.0. Всё ещё работает, но выводит предупреждение console.warn об устаревании один раз за сессию (начиная с v2.2.1 — вызовите resetDetectionCache(), чтобы предупреждение появилось снова) и будет удалена в v3.0. Полный changelog v1→v2 см. в разделе Миграция.

ts
detectIsiOS() // ⚠ устарело — выводит console.warn один раз за сессию
detectIsIOS() // ✓ используйте это вместо

Категория устройства ​

Быстрые грубые проверки, группирующие значения ОС в категории «мобильное» и «десктопное».

ts
import { isMobileDevice, isDesktopDevice } from 'os-detect'

isMobileDevice() // true, если iOS или Android
isDesktopDevice() // true, если macOS, Windows, Linux или ChromeOS

Заметка: isMobileDevice() и isDesktopDevice() не являются взаимоисключающими. Устройство с нераспознанной ОС вернёт false для обеих. На текущем наборе распознаваемых значений ОС пересечений нет.

Форм-фактор и ввод ​

getFormFactor() ​

FormFactor — 'phone' | 'tablet' | 'desktop' | 'tv' | 'unknown'

Определяется по ОС и физическому размеру экрана — не по наличию сенсорного экрана, так что сенсорный ноутбук на Windows всё равно вернёт 'desktop', никогда не 'tablet'. Порядок разрешения:

  1. detectIsTV() равно true → 'tv'
  2. iOS или Android, меньшая сторона экрана >= 768px (классическая граница для планшета) → 'tablet', иначе 'phone'
  3. macOS, Windows, Linux или ChromeOS → 'desktop'
  4. Всё остальное, либо нет screen для измерения (Node.js/SSR) → 'unknown'
ts
import { getFormFactor } from 'os-detect'

const formFactor = getFormFactor()

Тип FormFactor ​

ts
type FormFactor = 'phone' | 'tablet' | 'desktop' | 'tv' | 'unknown'

detectHasTouch() ​

boolean

true, если у устройства вообще есть сенсорный экран, независимо от того, какой тип ввода сейчас основной. В Node.js всегда false. Сначала проверяет navigator.maxTouchPoints, затем переходит на устаревшее navigator.msMaxTouchPoints и, наконец, на 'ontouchstart' in window.

ts
import { detectHasTouch } from 'os-detect'

detectHasTouch() // true на любом устройстве с сенсорным экраном — включая гибридные ноутбуки

getPrimaryInput() ​

PrimaryInput — 'mouse' | 'touch' | 'unknown'

Не кэшируется — в отличие от всех остальных функций на этой странице, getPrimaryInput() заново читает медиа-фичу pointer при каждом вызове, поскольку основной тип ввода может по-настоящему измениться прямо во время сессии (у гибридного устройства подключили или отключили клавиатуру/мышь). Читает window.matchMedia('(pointer: fine)') и (pointer: coarse); возвращает 'unknown', если matchMedia недоступен (старые браузеры, Node.js/SSR) или ни один из запросов не совпал. Используйте usePrimaryInput() из os-detect/vue или os-detect/react, чтобы реагировать на это вживую, вместо того чтобы опрашивать эту функцию вручную.

ts
import { getPrimaryInput } from 'os-detect'

getPrimaryInput() // 'mouse' | 'touch' | 'unknown'

Тип PrimaryInput ​

ts
type PrimaryInput = 'mouse' | 'touch' | 'unknown'

getPixelRatio() ​

number — window.devicePixelRatio, либо 1 в Node.js/SSR

Не кэшируется — дёшево читать вживую, а значение может измениться на десктопе, когда окно перетаскивают между мониторами с разным масштабированием.

ts
import { getPixelRatio } from 'os-detect'

getPixelRatio() // например, 2 на Retina-экране

detectIsTV() ​

boolean

Best-effort совпадение с известными платформами смарт-ТВ (Tizen, webOS, Android TV/Google TV, HbbTV, Fire TV, Sony BRAVIA, VIDAA). В Node.js всегда false.

ts
import { detectIsTV } from 'os-detect'

detectIsTV() // true на Samsung Tizen TV, LG webOS TV, Android TV и т. д.

Заметка: определение ТВ по userAgent по своей природе best-effort — некоторые браузеры смарт-ТВ отправляют почти обычный Android/Chrome userAgent вообще без надёжного ТВ-специфичного маркера, и на них возможен недодетект. Функция спроектирована так, чтобы никогда не принять телефон, планшет или десктоп за телевизор.

Рантайм-окружение ​

getRuntime() ​

Runtime — 'node' | 'browser' | 'webworker' | 'unknown'

Проверяется в этом порядке: detectIsWebWorker() → detectIsBrowser() → detectIsNode(). 'browser' побеждает 'node', когда присутствуют и window, и process — это renderer-процесс Electron/NW.js с включённой Node-интеграцией — см. detectIsElectron() ниже, чтобы отличить этот случай от обычной вкладки браузера.

ts
import { getRuntime } from 'os-detect'

getRuntime() // 'browser' во вкладке, 'node' в обычном скрипте, 'webworker' внутри Worker

Тип Runtime ​

ts
type Runtime = 'node' | 'browser' | 'webworker' | 'unknown'

detectIsNode() ​

boolean

true в обычном Node.js-скрипте, главном процессе Electron, либо renderer-процессе Electron/NW.js с включённой Node-интеграцией. Читает process.versions.node напрямую, поэтому остаётся точной, даже когда одновременно присутствует браузероподобный navigator.

ts
import { detectIsNode } from 'os-detect'

detectIsNode() // true везде, где задан process.versions.node

detectIsBrowser() ​

boolean

true, когда существуют и window, и document: реальная вкладка браузера или renderer-процесс Electron/NW.js. false в Node.js, внутри Web Worker и во время SSR.

ts
import { detectIsBrowser } from 'os-detect'

detectIsBrowser() // false на сервере, true после гидратации

detectIsWebWorker() ​

boolean

true внутри Dedicated, Shared или Service Worker. Проверяет наличие self без window, плюс importScripts (определён на WorkerGlobalScope, от которого наследуют все три типа worker'ов) — одного self без window недостаточно, поскольку в обычном Node.js нет ни того, ни другого.

ts
import { detectIsWebWorker } from 'os-detect'

detectIsWebWorker() // true только внутри контекста Worker

detectIsElectron() ​

boolean

true в главном процессе Electron либо в renderer-процессе, с включённой Node-интеграцией или без неё. Сначала проверяет process.versions.electron, а для изолированного (sandboxed/contextIsolated) renderer-процесса, где process вообще не доступен коду страницы, переходит на токен Electron/ в navigator.userAgent.

ts
import { getRuntime, detectIsElectron } from 'os-detect'

if (getRuntime() === 'browser' && detectIsElectron()) {
  console.log('Работаем внутри renderer-процесса Electron')
}

detectIsPWA() ​

boolean

true, когда приложение запущено установленным, в собственном автономном окне, а не в обычной вкладке браузера. В Node.js всегда false. Проверяет по порядку: медиа-фичи display-mode: standalone и display-mode: window-controls-overlay, устаревший флаг iOS Safari navigator.standalone, и referrer вида android-app:// для Trusted Web Activity.

ts
import { detectIsPWA } from 'os-detect'

detectIsPWA() // true после установки и запуска в автономном режиме

Типы TypeScript ​

Все публичные типы экспортируются из корня пакета:

ts
import type { OS, FormFactor, Runtime, PrimaryInput } from 'os-detect'

// OS: 'ios' | 'macos' | 'android' | 'windows' | 'linux' | 'chromeos' | 'unknown'
// FormFactor: 'phone' | 'tablet' | 'desktop' | 'tv' | 'unknown'
// Runtime: 'node' | 'browser' | 'webworker' | 'unknown'
// PrimaryInput: 'mouse' | 'touch' | 'unknown'

Сужение типа через getOS() ​

ts
import { getOS } from 'os-detect'
import type { OS } from 'os-detect'

const os: OS = getOS()

switch (os) {
  case 'ios':
  case 'android':
    console.log('Mobile device')
    break
  case 'windows':
  case 'macos':
  case 'linux':
  case 'chromeos':
    console.log('Desktop device')
    break
  case 'unknown':
    console.log('Unrecognised OS')
    break
}

TypeScript знает, что после switch все ветки исчерпаны — отдельный default не нужен, если вы обрабатываете 'unknown'.