├── .gitignore ├── tests ├── is-float.test.ts ├── is-int.test.ts ├── is-numeric.test.ts ├── is-empty.test.ts ├── is-json.test.ts ├── is-html-id.ts └── is-url.test.ts ├── package.json ├── tsconfig.json ├── src └── index.ts ├── README.md └── README-v1.md /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /tests/is-float.test.ts: -------------------------------------------------------------------------------- 1 | import Is from "./../src"; 2 | 3 | test("Is float", () => { 4 | expect(Is.float(1.2)).toBe(true); 5 | 6 | expect(Is.float(1)).toBe(false); 7 | expect(Is.float(1.0)).toBe(false); // weird? 8 | expect(Is.float(null)).toBe(false); 9 | expect(Is.float("1.0")).toBe(false); 10 | expect(Is.float(undefined)).toBe(false); 11 | }); 12 | -------------------------------------------------------------------------------- /tests/is-int.test.ts: -------------------------------------------------------------------------------- 1 | import Is from "./../src"; 2 | 3 | test("Is int", () => { 4 | expect(Is.int(1)).toBe(true); 5 | expect(Is.int(0)).toBe(true); 6 | expect(Is.int(1.0)).toBe(true); 7 | 8 | expect(Is.int(1.1)).toBe(false); 9 | expect(Is.int("2")).toBe(false); 10 | expect(Is.int(null)).toBe(false); 11 | expect(Is.int(1.00001)).toBe(false); 12 | expect(Is.int(undefined)).toBe(false); 13 | }); 14 | -------------------------------------------------------------------------------- /tests/is-numeric.test.ts: -------------------------------------------------------------------------------- 1 | import Is from "../src"; 2 | 3 | test("Is numeric value", () => { 4 | expect(Is.numeric(1)).toBe(true); 5 | expect(Is.numeric(0)).toBe(true); 6 | expect(Is.numeric(1.0)).toBe(true); 7 | expect(Is.numeric(1.1)).toBe(true); 8 | expect(Is.numeric(1.00001)).toBe(true); 9 | expect(Is.numeric(+2)).toBe(true); 10 | expect(Is.numeric(-2)).toBe(true); 11 | expect(Is.numeric("2")).toBe(true); 12 | expect(Is.numeric("2.0")).toBe(true); 13 | expect(Is.numeric("+2")).toBe(true); 14 | expect(Is.numeric("-2")).toBe(true); 15 | 16 | expect(Is.numeric("/2")).toBe(false); 17 | expect(Is.numeric("*2")).toBe(false); 18 | expect(Is.numeric("2.")).toBe(false); 19 | expect(Is.numeric(null)).toBe(false); 20 | expect(Is.numeric(undefined)).toBe(false); 21 | }); 22 | -------------------------------------------------------------------------------- /tests/is-empty.test.ts: -------------------------------------------------------------------------------- 1 | import Is, { isEmpty } from "./../src"; 2 | 3 | describe("@mongez/supportive-is/isEmpty", () => { 4 | it("should be empty", () => { 5 | expect(isEmpty("")).toBe(true); 6 | expect(isEmpty([])).toBe(true); 7 | expect(isEmpty(new Map())).toBe(true); 8 | expect(isEmpty(new Set())).toBe(true); 9 | expect(isEmpty(new Date())).toBe(true); 10 | expect(isEmpty({})).toBe(true); 11 | expect(isEmpty(null)).toBe(true); 12 | expect(isEmpty(undefined)).toBe(true); 13 | }); 14 | 15 | it("should not be empty", () => { 16 | expect(isEmpty(0)).toBe(false); 17 | expect(isEmpty(1)).toBe(false); 18 | expect(isEmpty("0")).toBe(false); 19 | expect(isEmpty(false)).toBe(false); 20 | expect(isEmpty({ length: 0 })).toBe(false); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mongez/supportive-is", 3 | "version": "2.0.4", 4 | "description": "A lightweight tool to check variable types and other logical checks", 5 | "main": "src/index.ts", 6 | "scripts": { 7 | "test": "jest tests" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/hassanzohdy/supportive-is" 12 | }, 13 | "devDependencies": { 14 | "@types/jest": "^27.0.3", 15 | "jest": "^27.4.5", 16 | "ts-jest": "^27.1.2", 17 | "jest-esm-jsx-transform": "^1.0.0", 18 | "typescript": "^4.5.2" 19 | }, 20 | "jest": { 21 | "verbose": true, 22 | "transform": { 23 | "\\.js$": "jest-esm-jsx-transform", 24 | "^.+\\.tsx?$": "ts-jest" 25 | } 26 | }, 27 | "keywords": [ 28 | "is-array", 29 | "is-object", 30 | "is-function", 31 | "is-form-element", 32 | "is-jquery-object", 33 | "is-browser-chrome", 34 | "is-mobile", 35 | "is-desktop", 36 | "is-boolean", 37 | "is-string" 38 | ], 39 | "author": "hassanzohdy", 40 | "license": "MIT" 41 | } -------------------------------------------------------------------------------- /tests/is-json.test.ts: -------------------------------------------------------------------------------- 1 | import Is, { isJson } from "../src"; 2 | 3 | describe("@mongez/supportive-is/isJson", () => { 4 | it("should return true if the value is a valid JSON", () => { 5 | expect(isJson('{"name":"John"}')).toBe(true); 6 | expect(isJson('{"name":"John", "age": 30}')).toBe(true); 7 | expect( 8 | isJson('{"name":"John", "age": 30, "cars": ["Ford", "BMW", "Fiat"]}') 9 | ).toBe(true); 10 | expect( 11 | isJson( 12 | '{"name":"John", "age": 30, "cars": ["Ford", "BMW", "Fiat"], "children": {"name":"Mary", "age": 10}}' 13 | ) 14 | ).toBe(true); 15 | 16 | expect(isJson("[1, 2, 3]")).toBe(true); 17 | }); 18 | 19 | it("should return false if the value is not a valid JSON", () => { 20 | expect(isJson("")).toBe(false); 21 | expect(isJson(12)).toBe(false); 22 | expect(isJson("12")).toBe(false); 23 | expect(isJson("John")).toBe(false); 24 | 25 | expect(isJson(0)).toBe(false); 26 | expect(isJson({})).toBe(false); 27 | expect(isJson([])).toBe(false); 28 | expect(isJson(null)).toBe(false); 29 | expect(isJson(true)).toBe(false); 30 | expect(isJson(false)).toBe(false); 31 | expect(isJson(undefined)).toBe(false); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /tests/is-html-id.ts: -------------------------------------------------------------------------------- 1 | import Is from "../src"; 2 | 3 | describe("@mongez/supportive-is/Is.validHtmlId", () => { 4 | it("should return true if the given value is a valid html id", () => { 5 | expect(Is.validHtmlId("base-id")).toBe(true); 6 | expect(Is.validHtmlId("BASE-ID")).toBe(true); 7 | expect(Is.validHtmlId("has-dash")).toBe(true); 8 | expect(Is.validHtmlId("has.dots")).toBe(true); 9 | expect(Is.validHtmlId("has:colon")).toBe(true); 10 | expect(Is.validHtmlId("has-number-3")).toBe(true); 11 | expect(Is.validHtmlId("has_underscore")).toBe(true); 12 | expect(Is.validHtmlId("has::multiple::colons")).toBe(true); 13 | expect(Is.validHtmlId("has--multiple--dashes")).toBe(true); 14 | expect(Is.validHtmlId("has__multiple__underscores")).toBe(true); 15 | }); 16 | 17 | it("should return false if the given value is not a valid html id", () => { 18 | expect(Is.validHtmlId("1qq")).toBe(false); 19 | expect(Is.validHtmlId("myId-1-")).toBe(false); 20 | expect(Is.validHtmlId(null)).toBe(false); 21 | expect(Is.validHtmlId(undefined)).toBe(false); 22 | expect(Is.validHtmlId("has,comma")).toBe(false); 23 | expect(Is.validHtmlId("1-starts-with-number")).toBe(false); 24 | expect(Is.validHtmlId("_starts-with-underscore")).toBe(false); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /tests/is-url.test.ts: -------------------------------------------------------------------------------- 1 | import Is, { isUrl } from "../src"; 2 | 3 | describe("@mongez/supportive-is/isUrl", () => { 4 | it("should return true for valid url", () => { 5 | expect(isUrl("https://google.com")).toBe(true); 6 | expect(isUrl("https://www.google.com")).toBe(true); 7 | expect(isUrl("http://google.com")).toBe(true); 8 | expect(isUrl("http://www.google.com")).toBe(true); 9 | expect(isUrl("https://google.com:80")).toBe(true); 10 | expect( 11 | isUrl( 12 | "https://codesandbox.io/s/suspicious-lichterman-fsxkg6?file=/src/index.js" 13 | ) 14 | ).toBe(true); 15 | }); 16 | 17 | it("should return false for invalid url", () => { 18 | expect(Is.url("google")).toBe(false); 19 | expect(isUrl("www.google.com")).toBe(false); 20 | expect(isUrl("google.")).toBe(false); 21 | expect(isUrl("google.com")).toBe(false); 22 | expect(isUrl("google..com")).toBe(false); 23 | expect(isUrl("https://google.")).toBe(false); 24 | expect(isUrl("https://google..com")).toBe(false); 25 | expect(isUrl("https://google.com:")).toBe(false); 26 | expect(isUrl("https://google.com:80a")).toBe(false); 27 | expect(isUrl("")).toBe(false); 28 | expect(isUrl(false)).toBe(false); 29 | expect(isUrl(null)).toBe(false); 30 | expect(isUrl(undefined)).toBe(false); 31 | expect(isUrl(0)).toBe(false); 32 | expect(isUrl(12)).toBe(false); 33 | expect(isUrl("12")).toBe(false); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ 22 | // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | 26 | /* Modules */ 27 | "module": "commonjs", /* Specify what module code is generated. */ 28 | // "rootDir": "./", /* Specify the root folder within your source files. */ 29 | // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ 30 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 31 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 32 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 33 | // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ 34 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 35 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 36 | // "resolveJsonModule": true, /* Enable importing .json files */ 37 | // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ 38 | 39 | /* JavaScript Support */ 40 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ 41 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 42 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ 43 | 44 | /* Emit */ 45 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 46 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 47 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 48 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 49 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ 50 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 51 | // "removeComments": true, /* Disable emitting comments. */ 52 | // "noEmit": true, /* Disable emitting files from a compilation. */ 53 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 54 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ 55 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 56 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 58 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 59 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 60 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 61 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 62 | // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ 63 | // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ 64 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 65 | // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ 66 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 67 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 68 | 69 | /* Interop Constraints */ 70 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 71 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 72 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */ 73 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 74 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 75 | 76 | /* Type Checking */ 77 | "strict": true, /* Enable all strict type-checking options. */ 78 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ 79 | // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ 80 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 81 | // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ 82 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 83 | // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ 84 | // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ 85 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 86 | // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ 87 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ 88 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 89 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 90 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 91 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ 92 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 93 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ 94 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 95 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 96 | 97 | /* Completeness */ 98 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 99 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | declare let opr: any; 2 | declare let window: any; 3 | declare let document: any; 4 | declare let safari: any; 5 | 6 | /** 7 | * Determine whether the given value is a number whatever if its data type is String or Number 8 | */ 9 | export function isNumeric(value: any) { 10 | return /^[+-]?\d+(\.\d+)?([Ee][+-]?\d+)?$/g.test(String(value)); 11 | } 12 | 13 | /** 14 | * Check if the given value is int 15 | */ 16 | export const isInt = (value: any) => 17 | typeof value === "number" && /^\d+$/.test(String(value)); 18 | 19 | /** 20 | * Check if the given value is float 21 | */ 22 | export const isFloat = (value: any) => 23 | typeof value === "number" && /^\d+.(\d+)$/.test(String(value)); 24 | 25 | /** 26 | * Check if the given value is a regex 27 | */ 28 | export const isRegex = (value: any) => 29 | value && value.constructor.name === "RegExp"; 30 | 31 | /** 32 | * Check if the given value is an object 33 | */ 34 | export const isObject = (value: any) => value && typeof value === "object"; 35 | 36 | /** 37 | * Check if the given value is a plain object 38 | */ 39 | export const isPlainObject = (value: any) => 40 | value && value.constructor.name === "Object"; 41 | 42 | /** 43 | * Check if the given value is validId 44 | */ 45 | export const isValidId = (value: any) => 46 | Boolean(value && /^[A-Za-z]+[\w\-\:\.]*$/.test(String(value))); 47 | 48 | /** 49 | * Check if the given value is a form element 50 | */ 51 | export const isFormElement = (value: any) => 52 | typeof HTMLFormElement === "undefined" 53 | ? false 54 | : value instanceof HTMLFormElement; 55 | 56 | /** 57 | * Check if the given value is a form data 58 | */ 59 | export const isFormData = (value: any) => value instanceof FormData; 60 | 61 | /** 62 | * Check if the given value is iterable 63 | */ 64 | export const isIterable = (value: any) => 65 | value && typeof value[Symbol.iterator] === "function"; 66 | 67 | /** 68 | * Check if the given value is a scalar value 69 | */ 70 | export const isScalar = (value: any) => 71 | ["string", "boolean", "number", "symbol", "bigint"].includes(typeof value); 72 | 73 | /** 74 | * Check if the given value is a string 75 | */ 76 | export const isString = (value: any) => typeof value === "string"; 77 | 78 | /** 79 | * Check if the given value is a pr value 80 | */ 81 | export const isPrimitive = (value: any) => 82 | ["string", "boolean", "number", "bigint"].includes(typeof value); 83 | 84 | /** 85 | * Check if the given value is a promise 86 | */ 87 | export const isPromise = (value: any) => 88 | value && value.constructor.name === "Promise"; 89 | 90 | /** 91 | * Check if the given value is a date 92 | */ 93 | export const isDate = (value: any) => 94 | value && typeof value === "object" && value.constructor === Date; 95 | 96 | /** 97 | * Check if the given value is a generator 98 | */ 99 | export const isGenerator = (value: any) => 100 | value && 101 | typeof value === "object" && 102 | value.constructor.name === "GeneratorFunction"; 103 | 104 | /** 105 | * Check if the given value is empty 106 | * Zero does not considered empty 107 | * Empty object is considered empty 108 | * Empty array is considered empty 109 | */ 110 | export const isEmpty = (value: any) => { 111 | if ([0, true, false].includes(value)) return false; 112 | 113 | if (value === undefined || value === null || value === "") return true; 114 | 115 | // check for map and set 116 | if (value instanceof Map || value instanceof Set) { 117 | return value.size === 0; 118 | } 119 | 120 | if (isIterable(value)) { 121 | return value.length === 0; 122 | } 123 | 124 | if (isPlainObject(value)) { 125 | return Object.keys(value).length === 0; 126 | } 127 | 128 | // this is used here for zero 129 | if (isNumeric(value)) return false; 130 | 131 | return true; 132 | }; 133 | 134 | /** 135 | * Check if the given value is a valid json 136 | */ 137 | export const isJson = (value: any) => { 138 | if (!value || typeof value !== "string") return false; 139 | 140 | if (!["[", "{"].includes(value?.[0])) return false; 141 | 142 | try { 143 | JSON.parse(value); 144 | return true; 145 | } catch (e) { 146 | return false; 147 | } 148 | }; 149 | 150 | /** 151 | * Check if the given value is valid url 152 | */ 153 | export const isUrl = (value: any) => { 154 | try { 155 | new URL(value); 156 | return true; 157 | } catch (e) { 158 | return false; 159 | } 160 | }; 161 | 162 | /** 163 | * Check if the given value is a valid email 164 | */ 165 | export const isEmail = (value: any) => 166 | /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test( 167 | value 168 | ); 169 | 170 | /** 171 | * Check if current user is opening from mobile 172 | */ 173 | export const isMobile = { 174 | /** 175 | * Determine whether the current visitor is opening from an Android device 176 | */ 177 | android: () => navigator.userAgent.match(/Android/i) !== null, 178 | /** 179 | * Determine whether the current visitor is opening from an ios device 180 | */ 181 | ios: () => navigator.userAgent.match(/iPhone|iPad|iPod/i) !== null, 182 | /** 183 | * Determine whether the current visitor is opening from an Iphone 184 | */ 185 | iphone: () => navigator.userAgent.match(/iPhone/i) !== null, 186 | /** 187 | * Determine whether the current visitor is opening from an ipad 188 | */ 189 | ipad: () => navigator.userAgent.match(/iPad/i) !== null, 190 | /** 191 | * Determine whether the current visitor is opening from an ipod 192 | */ 193 | ipod: () => navigator.userAgent.match(/iPod/i) !== null, 194 | /** 195 | * Determine whether the current visitor is opening from an windows mobile 196 | */ 197 | windows: () => navigator.userAgent.match(/IEMobile/i) !== null, 198 | /** 199 | * Determine whether the current visitor is opening from mobile whatever its type 200 | */ 201 | any: () => Is.mobile.android() || Is.mobile.ios() || Is.mobile.windows(), 202 | }; 203 | 204 | /** 205 | * Determine if current user is opening from macOS 206 | */ 207 | export const isMac = () => navigator.userAgent.match(/mac/i) !== null; 208 | 209 | /** 210 | * Check if current browser is the given name 211 | */ 212 | export const isBrowser = ( 213 | browser: "chrome" | "safari" | "firefox" | "opera" | "edge" | "ie" 214 | ) => { 215 | // Opera 8.0+ 216 | let isOpera = 217 | (!!window.opr && !!opr.addons) || 218 | !!window.opera || 219 | navigator.userAgent.indexOf(" OPR/") >= 0; 220 | 221 | // Firefox 1.0+ 222 | const isFirefox = typeof window.InstallTrigger !== "undefined"; 223 | 224 | // Safari 3.0+ "[object HTMLElementConstructor]" 225 | const isSafari = 226 | /constructor/i.test(window.HTMLElement) || 227 | ((p) => { 228 | return p.toString() === "[object SafariRemoteNotification]"; 229 | })( 230 | !window["safari"] || 231 | (typeof safari !== "undefined" && safari.pushNotification) 232 | ); 233 | 234 | // Internet Explorer 6-11 235 | const isIE = !!document.documentMode; 236 | 237 | // Edge 20+ 238 | const isEdge = !isIE && !!window.StyleMedia; 239 | 240 | // Chrome 1 - 71 241 | const isChrome = 242 | !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime); 243 | 244 | const browsersList: { [key: string]: boolean } = { 245 | chrome: isChrome, 246 | firefox: isFirefox, 247 | opera: isOpera, 248 | edge: isEdge, 249 | ie: isIE, 250 | safari: isSafari, 251 | }; 252 | 253 | return browsersList[browser.toLowerCase()] === true; 254 | }; 255 | 256 | /** 257 | * Check if current browser is chrome browser 258 | */ 259 | export const isChrome = () => 260 | !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime); 261 | 262 | /** 263 | * Check if current browser is firefox 264 | */ 265 | export const isFirefox = () => typeof window.InstallTrigger !== "undefined"; 266 | 267 | /** 268 | * Check if current browser is safari 269 | */ 270 | export const isSafari = () => { 271 | const isSafari = 272 | /constructor/i.test(window.HTMLElement) || 273 | ((p) => { 274 | return p.toString() === "[object SafariRemoteNotification]"; 275 | })( 276 | !window["safari"] || 277 | (typeof safari !== "undefined" && safari.pushNotification) 278 | ); 279 | return isSafari; 280 | }; 281 | 282 | /** 283 | * Check if current browser is opera 284 | */ 285 | export const isOpera = () => { 286 | let isOpera = 287 | (!!window.opr && !!opr.addons) || 288 | !!window.opera || 289 | navigator.userAgent.indexOf(" OPR/") >= 0; 290 | return isOpera; 291 | }; 292 | 293 | /** 294 | * Check if current browser is internet explorer 295 | */ 296 | export const isIE = () => !!document.documentMode; 297 | 298 | /** 299 | * Check if current browser is edge 300 | */ 301 | export const isEdge = () => { 302 | // Internet Explorer 6-11 303 | const isIE = !!document.documentMode; 304 | 305 | const isEdge = !isIE && !!window.StyleMedia; 306 | return isEdge; 307 | }; 308 | 309 | /** 310 | * Determine whether the current visitor is opening from desktop 311 | */ 312 | export const isDesktop = () => !isMobile.any(); 313 | 314 | /** 315 | * A simple lightweight library to validate values against certain types of data 316 | * For full documentation on github 317 | * Repo: https://github.com/hassanzohdy/supportive-is 318 | * 319 | * First released 01/12/2017 320 | * Licensed under MIT (http://opensource.org/licenses/MIT) 321 | */ 322 | export const Is = { 323 | /** 324 | * Determine whether the given value is a number whatever if its data type is String or Number 325 | */ 326 | numeric: isNumeric, 327 | /** 328 | * Determine whether the given value is an integer and its data type is number 329 | * As Number.isInteger considers 1.0 to be valid integer, regex will be used instead 330 | */ 331 | int: isInt, 332 | /** 333 | * Determine whether the given value is a float number and its data type is number 334 | */ 335 | float: isFloat, 336 | /** 337 | * Determine whether the given value is a regular expression 338 | */ 339 | regex: isRegex, 340 | /** 341 | * Determine whether the given value is an object 342 | */ 343 | object: isObject, 344 | /** 345 | * Determine whether the given value is a plain object 346 | */ 347 | plainObject: isPlainObject, 348 | /** 349 | * Determine whether the given value is an array 350 | */ 351 | array: Array.isArray, 352 | /** 353 | * Determine whether the given value is valid html attribute `id` 354 | */ 355 | validHtmlId: isValidId, 356 | /** 357 | * determine if the given value is an instance of form element 358 | */ 359 | formElement: isFormElement, 360 | /** 361 | * @alias formElement 362 | */ 363 | form: isFormElement, 364 | /** 365 | * determine if the given value is an instance of form data 366 | */ 367 | formData: isFormData, 368 | /** 369 | * Determine whether the given value is iterable 370 | */ 371 | iterable: isIterable, 372 | /** 373 | * Determine whether the given value is a scalar 374 | * Scalar types are strings, booleans, integers and 375 | */ 376 | scalar: isScalar, 377 | /** 378 | * Determine if the given value is a primitive value 379 | */ 380 | primitive: isPrimitive, 381 | /** 382 | * Determine whether the given value is a promise 383 | */ 384 | promise: isPromise, 385 | /** 386 | * Determine whether the given value is a date 387 | */ 388 | date: isDate, 389 | /** 390 | * Determine whether the given value is a generator 391 | */ 392 | generator: isGenerator, 393 | /** 394 | * Determine whether the given value if an empty 395 | * This can be validated against any type of values 396 | * undefined or nullable values will be considered empty 397 | * Objects that doesn't have any properties will be considered empty 398 | * Arrays and Strings will be empty based on its length 399 | * The 0 'Zero" number will not be considered empty 400 | */ 401 | empty: isEmpty, 402 | /** 403 | * Determine whether the given value is a valid json string 404 | */ 405 | json: isJson, 406 | /** 407 | * Determine whether the given value is a valid url 408 | */ 409 | url: isUrl, 410 | /** 411 | * Determine whether the given value is a valid email 412 | */ 413 | email: isEmail, 414 | /** 415 | * Determine the current visitor is opening from mobile 416 | * Please Note this method depends on the user agent 417 | */ 418 | mobile: isMobile, 419 | /** 420 | * Determine if current user is opening from macOS 421 | */ 422 | mac: isMac, 423 | /** 424 | * Determine whether the current visitor is opening from desktop 425 | */ 426 | desktop: isDesktop, 427 | /** 428 | * Check if the current browser is the given name 429 | * To detect browser version as well, pass the version number as the second argument 430 | */ 431 | browser: isBrowser, 432 | chrome: isChrome, 433 | firefox: isFirefox, 434 | safari: isSafari, 435 | opera: isOpera, 436 | ie: isIE, 437 | edge: isEdge, 438 | }; 439 | 440 | export default Is; 441 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Supportive Is 2 | 3 | A very lightweight library to validate different things 4 | 5 | ## Installation 6 | 7 | `npm i @mongez/supportive-is` 8 | 9 | Or using Yarn 10 | 11 | `yarn add @mongez/supportive-is` 12 | 13 | ## Version 1 14 | 15 | Read the previous version documentation from [here](./README-v1.md). 16 | 17 | ## Usage 18 | 19 | In older version, all checkers are exported in teh default object `Is`, but from version 2, each method is separated in its own function, this will increase performance when tree shaking is enabled. 20 | 21 | ```ts 22 | // Old Way 23 | import Is from "@mongez/supportive-is"; 24 | 25 | console.log(Is.empty({})); // true 26 | 27 | // New Way 28 | import { isEmpty } from "@mongez/supportive-is"; 29 | 30 | console.log(isEmpty({})); // true 31 | ``` 32 | 33 | ## Primitives 34 | 35 | We've tons of primitives to be checked, here are some of them. 36 | 37 | ## Is Primitive 38 | 39 | Check if the given value is a `string`, `number`, `boolean`, `null`, or `symbol` 40 | 41 | ```ts 42 | import { isPrimitive } from "@mongez/supportive-is"; 43 | 44 | console.log(isPrimitive("hello")); // true 45 | console.log(isPrimitive(22.5)); // true 46 | console.log(isPrimitive(false)); // true 47 | console.log(isPrimitive(null)); // true 48 | console.log(isPrimitive(Symbol("SymbolKey"))); // true 49 | console.log(isPrimitive([])); // false 50 | console.log(isPrimitive({})); // false 51 | ``` 52 | 53 | ## Is Scalar 54 | 55 | Check if the given value is a `string`, `number`, `bigInt` or `boolean` 56 | 57 | ```ts 58 | import { isScalar } from "@mongez/supportive-is"; 59 | 60 | console.log(isScalar("hello")); // true 61 | console.log(isScalar(22.5)); // true 62 | console.log(isScalar(false)); // true 63 | console.log(isScalar(null)); // false 64 | console.log(isScalar(undefined)); // false 65 | console.log(isScalar([])); // false 66 | console.log(isScalar({})); // false 67 | ``` 68 | 69 | ## Is Json 70 | 71 | Check if the given value string is a valid json format 72 | 73 | ```ts 74 | import { isJson } from "@mongez/supportive-is"; 75 | 76 | let value = '{"name":"Hasan","job":"Software Engineer"}'; 77 | 78 | console.log(isJson(value)); // true 79 | ``` 80 | 81 | ## Is String 82 | 83 | Check if the given value is a string 84 | 85 | ```ts 86 | import { isString } from "@mongez/supportive-is"; 87 | 88 | let myString = "hello world"; 89 | 90 | console.log(isString(myString)); // true 91 | ``` 92 | 93 | ## Is numeric 94 | 95 | Check if the given value is a number whether if its data type is `String` or `Number` 96 | 97 | ```ts 98 | import { isNumeric } from "@mongez/supportive-is"; 99 | 100 | let numberInt = 12; 101 | console.log(isNumeric(numberInt)); // true 102 | 103 | let numberFloat = 12.55; 104 | console.log(isNumeric(numberFloat)); // true 105 | 106 | let numberWrittenInString = "99"; 107 | console.log(isNumeric(numberWrittenInString)); // true 108 | 109 | let floatWrittenInString = "99.99"; 110 | console.log(isNumeric(floatWrittenInString)); // true 111 | ``` 112 | 113 | ## Is.int 114 | 115 | Check if the given value is an integer and its data type is number 116 | 117 | ```ts 118 | import { isInt } from "@mongez/supportive-is"; 119 | 120 | let number = 12; 121 | console.log(isInt(numberInt)); // true 122 | 123 | let numberInString = "12"; 124 | console.log(isInt(numberInString)); // false 125 | ``` 126 | 127 | ## Is float 128 | 129 | Check if the given value is a float number and its data type is number 130 | 131 | ```ts 132 | import { isFloat } from "@mongez/supportive-is"; 133 | 134 | let number = 921; 135 | console.log(isFloat(number)); // true 136 | 137 | number = 82.42; 138 | console.log(isFloat(number)); // true 139 | 140 | let numberInString = "12"; 141 | console.log(isFloat(numberInString)); // false 142 | 143 | let floatInString = "12.5"; 144 | 145 | console.log(isFloat(floatInString)); // false 146 | ``` 147 | 148 | ## Is Regex 149 | 150 | Check if the given value is a regular expression 151 | 152 | ```ts 153 | import { isRegex } from "@mongez/supportive-is"; 154 | 155 | let regex = /hello/; 156 | 157 | console.log(isRegex(regex)); // true 158 | 159 | let regexString = "/hello/"; 160 | 161 | console.log(isRegex(regexString)); // false 162 | 163 | let regexObject = new RegExp("hello"); 164 | 165 | console.log(isRegex(regexObject)); // true 166 | ``` 167 | 168 | ## Is Object 169 | 170 | Check if the given value is an object 171 | 172 | Any type of objects will be validated as true no matter its object type 173 | 174 | > Arrays are types of objects so any passed array will be validated as true 175 | > null values are considered objects in javascript, but it will be validated as false if provided. 176 | 177 | ```ts 178 | import { isObject } from "@mongez/supportive-is"; 179 | 180 | let myObject = {}; 181 | console.log(isObject(myObject)); // true 182 | 183 | class myClass {} 184 | let anotherObject = new myClass(); 185 | console.log(isObject(myObject)); // true 186 | 187 | let myArray = []; 188 | console.log(isObject(myArray)); // true 189 | 190 | console.log(isObject(null)); // false 191 | 192 | // to check if the given value is an object but not an array 193 | //you must mix between isObject AND Is.array to avoid an array 194 | if (isObject(myVar) && !Is.array(myVar)) { 195 | // do something with that object 196 | } 197 | ``` 198 | 199 | ## Is Array 200 | 201 | Check if the given value is an array 202 | 203 | ```ts 204 | import { isArray } from "@mongez/supportive-is"; 205 | 206 | let myArray = []; 207 | 208 | console.log(isArray(myArray)); // true 209 | ``` 210 | 211 | > This is just an alias to `Array.isArray` method 212 | 213 | ## Is PlainObject 214 | 215 | Check if the given value is a plain javascript object 216 | 217 | ```ts 218 | import { isPlainObject } from "@mongez/supportive-is"; 219 | 220 | // plain objects 221 | let myObject = {}; 222 | console.log(isPlainObject(myObject)); // true 223 | 224 | // classes 225 | class myClass {} 226 | let anotherObject = new myClass(); 227 | 228 | console.log(isPlainObject(myObject)); // false 229 | 230 | // arrays 231 | let myArray = []; 232 | 233 | console.log(isPlainObject(myArray)); // false 234 | 235 | // null value 236 | console.log(isPlainObject(null)); // false 237 | ``` 238 | 239 | ## Is iterable 240 | 241 | Check if the given value is iterable 242 | 243 | ```ts 244 | import { isIterable } from "@mongez/supportive-is"; 245 | 246 | let myArray = [1, 2, 3]; 247 | 248 | console.log(isIterable(myArray)); // true 249 | 250 | let myObject = { a: 1, b: 2, c: 3 }; 251 | 252 | console.log(isIterable(myObject)); // true 253 | 254 | let myString = "hello"; 255 | 256 | console.log(isIterable(myString)); // true 257 | 258 | let myNumber = 123; 259 | 260 | console.log(isIterable(myNumber)); // false 261 | 262 | let myBoolean = true; 263 | 264 | console.log(isIterable(myBoolean)); // false 265 | 266 | let myFunction = function () {}; 267 | 268 | console.log(isIterable(myFunction)); // false 269 | 270 | let myNull = null; 271 | 272 | console.log(isIterable(myNull)); // false 273 | 274 | let myUndefined = undefined; 275 | 276 | console.log(isIterable(myUndefined)); // false 277 | ``` 278 | 279 | It works fine as well with any class that implements the **Symbol.iterator** method 280 | 281 | ```ts 282 | class myClass { 283 | *[Symbol.iterator]() { 284 | yield 1; 285 | yield 2; 286 | yield 3; 287 | } 288 | } 289 | 290 | let myObject = new myClass(); 291 | 292 | console.log(Is.iterable(myObject)); // true 293 | ``` 294 | 295 | ## Is empty 296 | 297 | Check if the given value is empty. 298 | 299 | > This is a kind of smart method that will validate the given value whether it is empty or not based on its type 300 | 301 | ```ts 302 | import { isEmpty } from "@mongez/supportive-is"; 303 | 304 | // undefined values are considered empty 305 | let value = undefined; 306 | console.log(isEmpty(value)); // true 307 | 308 | // null values are considered empty 309 | value = null; 310 | console.log(isEmpty(value)); // true 311 | 312 | // Also any objects with no values are considered empty 313 | value = {}; 314 | console.log(isEmpty(value)); // true 315 | 316 | value.name = "Hasan"; 317 | console.log(isEmpty(value)); // false 318 | 319 | // Arrays 320 | value = []; 321 | console.log(isEmpty(value)); // true 322 | 323 | value.push(12); 324 | console.log(isEmpty(value)); // false 325 | 326 | // The `Zero` is not considered as empty value 327 | value = 0; 328 | console.log(isEmpty(value)); // false 329 | ``` 330 | 331 | ## Is.generator 332 | 333 | Check if the given value is a generator 334 | 335 | ```ts 336 | function* myGenerator() { 337 | yield 1; 338 | yield 2; 339 | yield 3; 340 | } 341 | 342 | let myGeneratorObject = myGenerator(); 343 | 344 | console.log(Is.generator(myGeneratorObject)); // true 345 | ``` 346 | 347 | ## Is.url 348 | 349 | Check if the given value is a valid url 350 | 351 | ```ts 352 | import { isUrl } from "@mongez/supportive-is"; 353 | 354 | let url = "google.com"; 355 | console.log(isUrl(url)); // true 356 | 357 | url = "https://google.com"; 358 | console.log(isUrl(url)); // true 359 | 360 | url = "www.google.com"; 361 | console.log(isUrl(url)); // true 362 | url = "www.google.com:8080"; 363 | console.log(isUrl(url)); // true 364 | 365 | url = "www.google.com?q=hello+world"; 366 | console.log(isUrl(url)); // true 367 | 368 | let url = "google"; 369 | console.log(isUrl(url)); // false 370 | ``` 371 | 372 | ## Is email 373 | 374 | Check if the given value string is a valid email 375 | 376 | ```ts 377 | import { isEmail } from "@mongez/supportive-is"; 378 | 379 | let myEmail = "hassanzohdy@gmail.com"; 380 | console.log(isEmail(myEmail)); // true 381 | ``` 382 | 383 | ## Is date 384 | 385 | Check if the given value is a date 386 | 387 | ```ts 388 | import { isDate } from "@mongez/supportive-is"; 389 | 390 | let myDate = new Date(); 391 | 392 | console.log(isDate(myDate)); // true 393 | ``` 394 | 395 | ## Is promise 396 | 397 | Check if the given value is a promise 398 | 399 | ```ts 400 | import { isPromise } from "@mongez/supportive-is"; 401 | 402 | let myPromise = new Promise((resolve, reject) => { 403 | resolve("hello world"); 404 | }); 405 | 406 | console.log(isPromise(myPromise)); // true 407 | ``` 408 | 409 | ## Is form element 410 | 411 | Check if the given value is a form element 412 | 413 | ```ts 414 | import { isFormElement } from "@mongez/supportive-is"; 415 | 416 | let myForm = document.querySelector("form"); 417 | 418 | console.log(isFormElement(myForm)); // true 419 | ``` 420 | 421 | > Is.formElement is an alias for Is.form 422 | 423 | ## Is formData 424 | 425 | Check if the given value is a form data 426 | 427 | ```ts 428 | import { isFormData } from "@mongez/supportive-is"; 429 | 430 | let myFormData = new FormData(); 431 | 432 | console.log(isFormData(myFormData)); // true 433 | ``` 434 | 435 | ## Is browser 436 | 437 | Check if current browser matches the given name 438 | 439 | ```ts 440 | import { isBrowser } from "@mongez/supportive-is"; 441 | 442 | console.log(isBrowser("chrome")); 443 | console.log(isBrowser("firefox")); 444 | console.log(isBrowser("safari")); 445 | console.log(isBrowser("opera")); 446 | console.log(isBrowser("edge")); 447 | console.log(isBrowser("ie")); 448 | ``` 449 | 450 | ## Is validHtmlId 451 | 452 | Check if the given value is a valid html id 453 | 454 | ```ts 455 | import { isValidHtmlId } from "@mongez/supportive-is"; 456 | 457 | let id = "myId"; 458 | 459 | console.log(isValidHtml(id)); // true 460 | 461 | id = "myId-1"; 462 | 463 | console.log(isValidHtml(id)); // true 464 | 465 | id = "myId-1-1"; 466 | 467 | console.log(isValidHtml(id)); // true 468 | 469 | id = "myId-1-"; 470 | 471 | console.log(isValidHtml(id)); // false 472 | ``` 473 | 474 | ## Is mobile 475 | 476 | Check if current visitor is browsing from a sort-of mobile 477 | 478 | > this property contains set of methods 479 | 480 | ```ts 481 | import { isMobile } from "@mongez/supportive-is"; 482 | // To check if user is browsing from an android device 483 | if (isMobile.android()) { 484 | // do something 485 | } 486 | 487 | // To check if user is browsing from an ios device 488 | if (isMobile.ios()) { 489 | // do something 490 | } 491 | 492 | // To check if user is browsing from an iphone 493 | if (isMobile.iphone()) { 494 | // do something 495 | } 496 | 497 | // To check if user is browsing from an ipad 498 | if (isMobile.ipad()) { 499 | // do something 500 | } 501 | 502 | // To check if user is browsing from an ipod 503 | if (isMobile.ipod()) { 504 | // do something 505 | } 506 | 507 | // To check if user is browsing from a windows mobile 508 | if (isMobile.windows()) { 509 | // do something 510 | } 511 | 512 | // To check if user is browsing from any type of mobile 513 | if (isMobile.any()) { 514 | // do something 515 | } 516 | ``` 517 | 518 | ## Is desktop 519 | 520 | Check if current visitor is browsing from a desktop device 521 | 522 | > Please note that any non mobile type will be considered as desktop. 523 | 524 | ```ts 525 | import { isDesktop } from "@mongez/supportive-is"; 526 | 527 | if (!isDesktop()) { 528 | // do something 529 | } 530 | ``` 531 | 532 | ## Tests 533 | 534 | To run tests, run the following command 535 | 536 | ```bash 537 | npm run test 538 | ``` 539 | 540 | OR 541 | 542 | ```bash 543 | yarn test 544 | ``` 545 | 546 | ## Change Log 547 | 548 | - V2.0.0 (04 Sept 2023) 549 | - Separated each method in its own function 550 | - Removed many unused methods to reduce the package size 551 | - V1.0.7 (11 Oct 2022) 552 | - Added tests 553 | - Enhanced Documentation 554 | - Added more methods 555 | -------------------------------------------------------------------------------- /README-v1.md: -------------------------------------------------------------------------------- 1 | # Supportive Is 2 | 3 | A very lightweight library to validate different things 4 | 5 | ## Installation 6 | 7 | `npm i @mongez/supportive-is` 8 | 9 | Or using Yarn 10 | 11 | `yarn add @mongez/supportive-is` 12 | 13 | ## Usage 14 | 15 | There are many data types here to be checked, but firstly let's import the package 16 | 17 | ```ts 18 | import Is from '@mongez/supportive-is'; 19 | 20 | // use it 21 | ``` 22 | 23 | ## Primitives 24 | 25 | We've tons of primitives to be checked, here are some of them. 26 | 27 | ## Is.primitive 28 | 29 | Check if the given value is a `string`, `number`, `boolean`, `null`, `undefined` or `symbol` 30 | 31 | ```ts 32 | console.log(Is.primitive('hello')); // true 33 | console.log(Is.primitive(22.5)); // true 34 | console.log(Is.primitive(false)); // true 35 | console.log(Is.primitive(null)); // true 36 | console.log(Is.primitive(Symbol('SymbolKey'))); // true 37 | console.log(Is.primitive(undefined)); // true 38 | console.log(Is.primitive([])); // false 39 | console.log(Is.primitive({})); // false 40 | ``` 41 | 42 | ### Is.scalar 43 | 44 | Check if the given value is a `string`, `number` or `boolean` 45 | 46 | ```ts 47 | console.log(Is.scalar('hello')); // true 48 | console.log(Is.scalar(22.5)); // true 49 | console.log(Is.scalar(false)); // true 50 | console.log(Is.scalar(null)); // false 51 | console.log(Is.scalar(undefined)); // false 52 | console.log(Is.scalar([])); // false 53 | console.log(Is.scalar({})); // false 54 | ``` 55 | 56 | ### Is.json 57 | 58 | Check if the given value string is a valid json format 59 | 60 | ```ts 61 | let value = '{"name":"Hasan","job":"Software Engineer"}'; 62 | console.log(Is.json(value)); // true 63 | ``` 64 | 65 | ### Is.null 66 | 67 | Check if the given value is null 68 | 69 | ```ts 70 | let name = null; 71 | console.log(Is.null(name)); // true 72 | 73 | name = undefined; 74 | console.log(Is.null(name)); // false 75 | ``` 76 | 77 | ### Is.undefined 78 | 79 | Check if the given value is undefined 80 | 81 | ```ts 82 | let name = 'Hasan'; 83 | console.log(Is.undefined(name)); // false 84 | 85 | let myVar; // any declared variable without a value will be treated as undefined 86 | console.log(Is.undefined(myVar)); // true 87 | 88 | let age = undefined; 89 | console.log(Is.undefined(age)); // true 90 | ``` 91 | 92 | ### Is.numeric 93 | 94 | Check if the given value is a number whether if its data type is `String` or `Number` 95 | 96 | ```ts 97 | let numberInt = 12; 98 | console.log(Is.numeric(numberInt)); // true 99 | 100 | let numberFloat = 12.55; 101 | console.log(Is.numeric(numberFloat)); // true 102 | 103 | let numberWrittenInString = '99'; 104 | console.log(Is.numeric(numberWrittenInString)); // true 105 | 106 | let floatWrittenInString = '99.99'; 107 | console.log(Is.numeric(floatWrittenInString)); // true 108 | ``` 109 | 110 | ### Is.number 111 | 112 | Check if the given value is a number whether if its data type is `Number` 113 | 114 | ```ts 115 | let numberInt = 12; 116 | console.log(Is.number(numberInt)); // true 117 | 118 | let numberFloat = 12.55; 119 | 120 | console.log(Is.number(numberFloat)); // true 121 | 122 | let numberWrittenInString = '99'; 123 | 124 | console.log(Is.number(numberWrittenInString)); // false 125 | 126 | let floatWrittenInString = '99.99'; 127 | 128 | console.log(Is.number(floatWrittenInString)); // false 129 | ``` 130 | 131 | > The major difference between `Is.numeric` and `Is.number` is that `Is.numeric` will return true if the given value is a string that contains a number 132 | 133 | ### Is.int 134 | 135 | Check if the given value is an integer and its data type is number 136 | 137 | ```ts 138 | let number = 12; 139 | console.log(Is.int(numberInt)); // true 140 | 141 | let numberInString = '12'; 142 | console.log(Is.int(numberInString)); // false 143 | ``` 144 | 145 | ### Is.float 146 | 147 | Check if the given value is a float number and its data type is number 148 | 149 | ```ts 150 | let number = 921; 151 | console.log(Is.float(number)); // true 152 | 153 | number = 82.42; 154 | console.log(Is.float(number)); // true 155 | 156 | let numberInString = '12'; 157 | console.log(Is.float(numberInString)); // false 158 | ``` 159 | 160 | ### Is.string 161 | 162 | Check if the given value is string 163 | 164 | ```ts 165 | console.log(Is.string('this is a string')); // true 166 | ``` 167 | 168 | ### Is.bool 169 | 170 | Check if the given value is boolean 171 | 172 | ```ts 173 | console.log(Is.bool(true)); // true 174 | console.log(Is.bool(false)); // true 175 | ``` 176 | 177 | > Is.boolean is an alias for Is.bool 178 | 179 | ### Is.symbol 180 | 181 | Check if the given value is a symbol 182 | 183 | ```ts 184 | 185 | let mySymbol = Symbol('mySymbol'); 186 | 187 | console.log(Is.symbol(mySymbol)); // true 188 | ``` 189 | 190 | ### Is.NaN 191 | 192 | Check if the given value is Not a Number 193 | This method works exactly same as isNaN as it is already implementing it xD. 194 | 195 | ```ts 196 | let number = 76; // number int 197 | console.log(Is.NaN(number)); // false 198 | 199 | number = '76'; // string 200 | console.log(Is.NaN(number)); // true 201 | ``` 202 | 203 | ### Is.regex 204 | 205 | Check if the given value is a regular expression 206 | 207 | ```ts 208 | 209 | let regex = /hello/; 210 | 211 | console.log(Is.regex(regex)); // true 212 | 213 | let regexString = '/hello/'; 214 | 215 | console.log(Is.regex(regexString)); // false 216 | 217 | let regexObject = new RegExp('hello'); 218 | 219 | console.log(Is.regex(regexObject)); // true 220 | ``` 221 | 222 | ## Objects, Classes And Arrays 223 | 224 | Now let's check some objects. 225 | 226 | ### Is.object 227 | 228 | Check if the given value is an object 229 | 230 | Any type of objects will be validated as true no matter its object type 231 | 232 | > Arrays are types of objects so any passed array will be validated as true 233 | > null values are considered objects in javascript, but it will be validated as false if provided. 234 | 235 | ```ts 236 | let myObject = {}; 237 | console.log(Is.object(myObject)); // true 238 | 239 | class myClass {} 240 | let anotherObject = new myClass; 241 | console.log(Is.object(myObject)); // true 242 | 243 | let myArray = []; 244 | console.log(Is.object(myArray)); // true 245 | 246 | console.log(Is.object(null)); // false 247 | 248 | // to check if the given value is an object but not an array 249 | //you must mix between Is.object AND Is.array to avoid an array 250 | if (Is.object(myVar) && ! Is.array(myVar)) { 251 | // do something with that object 252 | } 253 | ``` 254 | 255 | ### Is.plainObject 256 | 257 | Check if the given value is a plain javascript object 258 | 259 | ```ts 260 | // plain objects 261 | let myObject = {}; 262 | console.log(Is.plainObject(myObject)); // true 263 | 264 | // classes 265 | class myClass {} 266 | let anotherObject = new myClass; 267 | 268 | console.log(Is.plainObject(myObject)); // false 269 | 270 | // arrays 271 | let myArray = []; 272 | 273 | console.log(Is.plainObject(myArray)); // false 274 | 275 | // null value 276 | console.log(Is.plainObject(null)); // false 277 | ``` 278 | 279 | ### Is.a 280 | 281 | Check if the given value is an instance of the given class 282 | 283 | ```ts 284 | class myClass {} 285 | 286 | let myObject = new myClass; 287 | 288 | console.log(Is.a(myObject, myClass)); // true 289 | ``` 290 | 291 | ### Is.array 292 | 293 | Check if the given value is an array 294 | 295 | ```ts 296 | let myArray = [4 , 'hello', 9]; 297 | console.log(Is.array(myArray)); // true 298 | ``` 299 | 300 | ### Is.iterable 301 | 302 | Check if the given value is iterable 303 | 304 | ```ts 305 | 306 | let myArray = [1, 2, 3]; 307 | 308 | console.log(Is.iterable(myArray)); // true 309 | 310 | let myObject = {a: 1, b: 2, c: 3}; 311 | 312 | console.log(Is.iterable(myObject)); // true 313 | 314 | let myString = 'hello'; 315 | 316 | console.log(Is.iterable(myString)); // true 317 | 318 | let myNumber = 123; 319 | 320 | console.log(Is.iterable(myNumber)); // false 321 | 322 | let myBoolean = true; 323 | 324 | console.log(Is.iterable(myBoolean)); // false 325 | 326 | let myFunction = function() {}; 327 | 328 | console.log(Is.iterable(myFunction)); // false 329 | 330 | let myNull = null; 331 | 332 | console.log(Is.iterable(myNull)); // false 333 | 334 | let myUndefined = undefined; 335 | 336 | console.log(Is.iterable(myUndefined)); // false 337 | ``` 338 | 339 | It works fine as well with any class that implements the **Symbol.iterator** method 340 | 341 | ```ts 342 | 343 | class myClass { 344 | *[Symbol.iterator]() { 345 | yield 1; 346 | yield 2; 347 | yield 3; 348 | } 349 | } 350 | 351 | let myObject = new myClass(); 352 | 353 | console.log(Is.iterable(myObject)); // true 354 | ``` 355 | 356 | ## Is.map 357 | 358 | Check if the given value is a map 359 | 360 | ```ts 361 | let myMap = new Map(); 362 | 363 | console.log(Is.map(myMap)); // true 364 | ``` 365 | 366 | ## Is.set 367 | 368 | Check if the given value is a set 369 | 370 | ```ts 371 | let mySet = new Set(); 372 | 373 | console.log(Is.set(mySet)); // true 374 | ``` 375 | 376 | ## Is.weakMap 377 | 378 | Check if the given value is a weak map 379 | 380 | ```ts 381 | let myWeakMap = new WeakMap(); 382 | 383 | console.log(Is.weakMap(myWeakMap)); // true 384 | ``` 385 | 386 | ## Is.weakSet 387 | 388 | Check if the given value is a weak set 389 | 390 | ```ts 391 | let myWeakSet = new WeakSet(); 392 | 393 | console.log(Is.weakSet(myWeakSet)); // true 394 | ``` 395 | 396 | ### Is.empty 397 | 398 | Check if the given value is empty. 399 | 400 | > This is a kind of smart method that will validate the given value whether it is empty or not based on its type 401 | 402 | ```ts 403 | 404 | // undefined values are considered empty 405 | let value = undefined; 406 | console.log(Is.empty(value)); // true 407 | 408 | // null values are considered empty 409 | value = null; 410 | console.log(Is.empty(value)); // true 411 | 412 | // Also any objects with no values are considered empty 413 | value = {}; 414 | console.log(Is.empty(value)); // true 415 | 416 | value.name = 'Hasan'; 417 | console.log(Is.empty(value)); // false 418 | 419 | // Arrays 420 | value = []; 421 | console.log(Is.empty(value)); // true 422 | 423 | value.push(12); 424 | console.log(Is.empty(value)); // false 425 | 426 | // The `Zero` is not considered as empty value 427 | value = 0; 428 | console.log(Is.empty(value)); // false 429 | ``` 430 | 431 | ## Functions And Generators 432 | 433 | ### Is.function 434 | 435 | Check if the given value is a function 436 | 437 | ```ts 438 | function sum(x, y) { 439 | return x + y; 440 | } 441 | 442 | // you must pass the function name not the function call 443 | console.log(Is.function(sum)); // true 444 | 445 | // if you passed the function call it will be not a function in this situation 446 | console.log(Is.function(sum(2, 3))); // false 447 | ``` 448 | 449 | > Is.callable is an alias for Is.function 450 | > Is.fn is an alias for Is.function 451 | 452 | ### Is.generator 453 | 454 | Check if the given value is a generator 455 | 456 | ```ts 457 | 458 | function* myGenerator() { 459 | yield 1; 460 | yield 2; 461 | yield 3; 462 | } 463 | 464 | let myGeneratorObject = myGenerator(); 465 | 466 | console.log(Is.generator(myGeneratorObject)); // true 467 | ``` 468 | 469 | ### Is.native 470 | 471 | Check if the given value is a native javascript function 472 | 473 | ```ts 474 | 475 | let myFunction = function() { 476 | return 'hello world'; 477 | }; 478 | 479 | console.log(Is.native(myFunction)); // false 480 | 481 | console.log(Is.native(Math.random)); // true 482 | ``` 483 | 484 | ## Misc 485 | 486 | ### Is.url 487 | 488 | Check if the given value is a valid url 489 | 490 | ```ts 491 | let url = 'google.com'; 492 | console.log(Is.url(url)); // true 493 | 494 | url = 'https://google.com'; 495 | console.log(Is.url(url)); // true 496 | 497 | url = 'www.google.com'; 498 | console.log(Is.url(url)); // true 499 | url = 'www.google.com:8080'; 500 | console.log(Is.url(url)); // true 501 | 502 | url = 'www.google.com?q=hello+world'; 503 | console.log(Is.url(url)); // true 504 | 505 | let url = 'google'; 506 | console.log(Is.url(url)); // false 507 | ``` 508 | 509 | ### Is.email 510 | 511 | Check if the given value string is a valid email 512 | 513 | ```ts 514 | let myEmail = 'hassanzohdy@gmail.com'; 515 | console.log(Is.email(myEmail)); // true 516 | ``` 517 | 518 | ### Is.date 519 | 520 | Check if the given value is a date 521 | 522 | ```ts 523 | 524 | let myDate = new Date(); 525 | 526 | console.log(Is.date(myDate)); // true 527 | ``` 528 | 529 | ### Is.promise 530 | 531 | Check if the given value is a promise 532 | 533 | ```ts 534 | 535 | let myPromise = new Promise((resolve, reject) => { 536 | resolve('hello world'); 537 | }); 538 | 539 | console.log(Is.promise(myPromise)); // true 540 | ``` 541 | 542 | ### Is.error 543 | 544 | Check if the given value is an error 545 | 546 | ```ts 547 | let myError = new Error('my error'); 548 | 549 | console.log(Is.error(myError)); // true 550 | ``` 551 | 552 | ## DOM & Browser 553 | 554 | ### Is.element 555 | 556 | Check if the given value is a dom element 557 | 558 | > Dom Elements are objects of **HTMLElement**, so any html element will be validated as true, something like **document.body** 559 | > **document** and **window** are not validated as true as they are not part of the html elements 560 | 561 | ```ts 562 | console.log(Is.element(document)); // false 563 | 564 | console.log(Is.element(document.body)); // true 565 | ``` 566 | 567 | > Is.dom is an alias for Is.element 568 | 569 | ### Is.form 570 | 571 | Check if the given value is a form element 572 | 573 | ```ts 574 | 575 | let myForm = document.querySelector('form'); 576 | 577 | console.log(Is.form(myForm)); // true 578 | ``` 579 | 580 | > Is.formElement is an alias for Is.form 581 | 582 | ### Is.formData 583 | 584 | Check if the given value is a form data 585 | 586 | ```ts 587 | let myFormData = new FormData(); 588 | 589 | console.log(Is.formData(myFormData)); // true 590 | ``` 591 | 592 | ### Is.browser 593 | 594 | Check if current browser matches the given name 595 | 596 | ```ts 597 | console.log(Is.browser('chrome')); 598 | console.log(Is.browser('firefox')); 599 | console.log(Is.browser('safari')); 600 | console.log(Is.browser('opera')); 601 | console.log(Is.browser('edge')); 602 | console.log(Is.browser('ie')); 603 | ``` 604 | 605 | ### Is.validHtmlId 606 | 607 | Check if the given value is a valid html id 608 | 609 | ```ts 610 | 611 | let id = 'myId'; 612 | 613 | console.log(Is.validHtmlId(id)); // true 614 | 615 | id = 'myId-1'; 616 | 617 | console.log(Is.validHtmlId(id)); // true 618 | 619 | id = 'myId-1-1'; 620 | 621 | console.log(Is.validHtmlId(id)); // true 622 | 623 | id = 'myId-1-'; 624 | 625 | console.log(Is.validHtmlId(id)); // false 626 | ``` 627 | 628 | ### Is.mobile.* 629 | 630 | Check if current visitor is browsing from a sort-of mobile 631 | 632 | > this property contains set of methods 633 | 634 | ```ts 635 | 636 | // To check if user is browsing from an android device 637 | if (Is.mobile.android()) { 638 | // do something 639 | } 640 | 641 | // To check if user is browsing from an ios device 642 | if (Is.mobile.ios()) { 643 | // do something 644 | } 645 | 646 | // To check if user is browsing from an iphone 647 | if (Is.mobile.iphone()) { 648 | // do something 649 | } 650 | 651 | // To check if user is browsing from an ipad 652 | if (Is.mobile.ipad()) { 653 | // do something 654 | } 655 | 656 | // To check if user is browsing from an ipod 657 | if (Is.mobile.ipod()) { 658 | // do something 659 | } 660 | 661 | // To check if user is browsing from a windows mobile 662 | if (Is.mobile.windows()) { 663 | // do something 664 | } 665 | 666 | // To check if user is browsing from any type of mobile 667 | if (Is.mobile.any()) { 668 | // do something 669 | } 670 | ``` 671 | 672 | ### Is.desktop 673 | 674 | Check if current visitor is browsing from a desktop device 675 | > Please note that any non mobile type will be considered as desktop. 676 | 677 | ```ts 678 | if (! Is.desktop()) { 679 | // do something 680 | } 681 | ``` 682 | 683 | ### Is.enabled.* 684 | 685 | Check for variant data that are enabled in the browser 686 | 687 | ```ts 688 | console.log(Is.enabled.cookies()); 689 | console.log(Is.enabled.localStorage()); 690 | console.log(Is.enabled.sessionStorage()); 691 | console.log(Is.enabled.indexedDB()); 692 | console.log(Is.enabled.webWorkers()); 693 | console.log(Is.enabled.serviceWorkers()); 694 | console.log(Is.enabled.notifications()); 695 | console.log(Is.enabled.pushNotifications()); 696 | console.log(Is.enabled.geoLocation()); // also geolocation is an alias (with lower L) 697 | console.log(Is.enabled.webRTC()); 698 | console.log(Is.enabled.webAudio()); 699 | console.log(Is.enabled.microphone()); 700 | console.log(Is.enabled.camera()); 701 | console.log(Is.enabled.speechRecognition()); 702 | console.log(Is.enabled.speechSynthesis()); 703 | console.log(Is.enabled.fullScreen()); // also fullscreen is an alias (with lower S) 704 | console.log(Is.enabled.vibration()); 705 | console.log(Is.enabled.touch()); 706 | console.log(Is.enabled.battery()); 707 | console.log(Is.enabled.fetch()); 708 | console.log(Is.enabled.history()); 709 | console.log(Is.enabled.darkMode()); // will validate prefers-color-scheme media query (dark mode) 710 | console.log(Is.enabled.lightMode()); // will validate prefers-color-scheme media query (light mode) 711 | console.log(Is.enabled.animation()); 712 | console.log(Is.enabled.transition()); 713 | ``` 714 | 715 | ## Tests 716 | 717 | To run tests, run the following command 718 | 719 | ```bash 720 | npm run test 721 | ``` 722 | 723 | OR 724 | 725 | ```bash 726 | yarn test 727 | ``` 728 | 729 | ## Change Log 730 | 731 | - 1.0.7 (11 Oct 2022) 732 | - Added tests 733 | - Enhanced Documentation 734 | - Added more methods 735 | --------------------------------------------------------------------------------