Advanced Usage
TypeScript types
All public types are exported from the package root:
import type { OS } from 'os-detect'
// OS is a string union:
// 'ios' | 'macos' | 'android' | 'windows' | 'linux' | 'chromeos' | 'unknown'Narrowing with getOS()
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 knows all branches are exhausted after the switch — no need for a default case if you handle 'unknown'.
React types
useOS() returns OS. useIsWindows11() returns boolean | null. Both are fully typed with no extra imports needed.
Vue types
useOS() returns Readonly<Ref<OS>>. useIsWindows11() returns Readonly<Ref<boolean | null>>.
import type { OS } from 'os-detect'
import { useOS } from 'os-detect/vue'
import type { Ref } from 'vue'
const os: Readonly<Ref<OS>> = useOS()Detection strategy
Browser
navigator.userAgentData.platform(Chrome 90+ / Edge 90+) — the modern, high-entropy-free platform hint. Reliable and not spoofable by userAgent overrides.navigator.userAgent— legacy fallback for all other browsers (Firefox, Safari, older Chrome). Regex patterns are kept conservative to avoid false positives.
For Windows 11, an additional async call to navigator.userAgentData.getHighEntropyValues(['platformVersion']) is required — this is gated behind detectIsWindows11() and never called automatically.
Node.js
Reads process.platform when navigator is absent. No userAgent parsing is done server-side. detectIsWindows11() dynamically imports the built-in os module and parses the build number from os.release().
Caching
Results are stored in module-level variables after the first call. Subsequent calls return the cached value directly with no DOM or process access. This makes repeated calls in reactive contexts (render functions, computed properties) effectively free.
Limitations
Every detector ultimately relies on navigator.userAgentData or navigator.userAgent (or process.platform in Node.js). This has two structural consequences:
- User agent strings can be spoofed by the browser, an extension, or devtools device emulation. There is no way to cryptographically verify the reported platform — treat results as a UX hint, not a security boundary.
navigator.userAgentDatais a moving target. Chromium is progressively freezing/reducing the legacynavigator.userAgentstring and gating more detail behind opt-in high-entropy values. Firefox and Safari don't implementuserAgentDataat all, so they always fall through to UA-string regexes. Future browser changes could require updated patterns — this is inherent to UA-based detection, not specific to this library.
Caching & resetDetectionCache
import { resetDetectionCache } from 'os-detect'
resetDetectionCache() // clears every cached detection resultAll detectIs*() functions and getOS() cache their result after the first call (see Caching above). In a normal browser tab the OS never changes mid-session, so this is never needed. It exists for advanced cases:
- A long-running Node.js process (e.g. an Electron main process) that needs to re-evaluate
process.platformafter switching contexts. - Test suites that mock
navigator/process.platformper test without re-importing the module.
detectIsWindows11() is not cached — it always re-runs its async check.