[6a3a178] | 1 | # is What? 🙉
|
---|
| 2 |
|
---|
| 3 | Very simple & small JS type check functions. It's fully TypeScript supported!
|
---|
| 4 |
|
---|
| 5 | ```
|
---|
| 6 | npm i is-what
|
---|
| 7 | ```
|
---|
| 8 |
|
---|
| 9 | Or for deno available at: `"deno.land/x/is_what"`
|
---|
| 10 |
|
---|
| 11 | ## Motivation
|
---|
| 12 |
|
---|
| 13 | I built is-what because the existing solutions were all too complex or too poorly built.
|
---|
| 14 |
|
---|
| 15 | I was looking for:
|
---|
| 16 | - A simple way to check any kind of type (including non-primitives)
|
---|
| 17 | - Be able to check if an object is a plain object `{}` or a special object (like a class instance) ‼️
|
---|
| 18 | - Let TypeScript automatically know what type a value is when checking
|
---|
| 19 |
|
---|
| 20 | And that's exactly what `is-what` is! (what a great wordplay 😃)
|
---|
| 21 |
|
---|
| 22 | ## Usage
|
---|
| 23 |
|
---|
| 24 | is-what is really easy to use, and most functions work just like you'd expect.
|
---|
| 25 |
|
---|
| 26 | ```js
|
---|
| 27 | // import functions you want to use like so:
|
---|
| 28 | import { isString, isDate, isPlainObject } from 'is-what'
|
---|
| 29 | ```
|
---|
| 30 |
|
---|
| 31 | 1. First I'll go over the simple functions available. Only `isNumber` and `isDate` have special treatment.
|
---|
| 32 | 2. After that I'll talk about working with Objects (plain objects vs class instances etc.).
|
---|
| 33 | 3. Lastly I'll talk about TypeScript implementation
|
---|
| 34 |
|
---|
| 35 | ### Simple type check functions
|
---|
| 36 |
|
---|
| 37 | ```js
|
---|
| 38 | // strings
|
---|
| 39 | isString('') // true
|
---|
| 40 | isEmptyString('') // true
|
---|
| 41 | isFullString('') // false
|
---|
| 42 |
|
---|
| 43 | // numbers
|
---|
| 44 | isNumber(0) // true
|
---|
| 45 | isNumber(NaN) // false
|
---|
| 46 |
|
---|
| 47 | // dates
|
---|
| 48 | isDate(new Date()) // true
|
---|
| 49 | isDate(new Date('invalid date')) // false
|
---|
| 50 |
|
---|
| 51 | // others
|
---|
| 52 | isBoolean(false) // true
|
---|
| 53 | isFunction(function () {}) // true
|
---|
| 54 | isArray([]) // true
|
---|
| 55 | isUndefined(undefined) // true
|
---|
| 56 | isNull(null) // true
|
---|
| 57 | isRegExp(/\s/gi) // true
|
---|
| 58 | isSymbol(Symbol()) // true
|
---|
| 59 | isBlob(new Blob()) // true
|
---|
| 60 | isFile(new File([''], '', { type: 'text/html' })) // true
|
---|
| 61 |
|
---|
| 62 | // primitives
|
---|
| 63 | isPrimitive('') // true
|
---|
| 64 | // true for any of: boolean, null, undefined, number, string, symbol
|
---|
| 65 | ```
|
---|
| 66 |
|
---|
| 67 | ### Getting and checking for specific types
|
---|
| 68 |
|
---|
| 69 | You can check for specific types with `getType` and `isType`:
|
---|
| 70 |
|
---|
| 71 | ```js
|
---|
| 72 | import { getType, isType } from 'is-what'
|
---|
| 73 |
|
---|
| 74 | getType('') // returns 'String'
|
---|
| 75 | // pass a Type as second param:
|
---|
| 76 | isType('', String) // returns true
|
---|
| 77 | ```
|
---|
| 78 |
|
---|
| 79 | ### isPlainObject vs isAnyObject
|
---|
| 80 |
|
---|
| 81 | Checking for a JavaScript object can be really difficult. In JavaScript you can create classes that will behave just like JavaScript objects but might have completely different prototypes. With is-what I went for this classification:
|
---|
| 82 |
|
---|
| 83 | - `isPlainObject` will only return `true` on plain JavaScript objects and not on classes or others
|
---|
| 84 | - `isAnyObject` will be more loose and return `true` on regular objects, classes, etc.
|
---|
| 85 |
|
---|
| 86 | ```js
|
---|
| 87 | // define a plain object
|
---|
| 88 | const plainObject = {hello: 'I am a good old object.'}
|
---|
| 89 |
|
---|
| 90 | // define a special object
|
---|
| 91 | class SpecialObject {
|
---|
| 92 | constructor (somethingSpecial) {
|
---|
| 93 | this.speciality = somethingSpecial
|
---|
| 94 | }
|
---|
| 95 | }
|
---|
| 96 | const specialObject = new SpecialObject('I am a special object! I am a class instance!!!')
|
---|
| 97 |
|
---|
| 98 | // check the plain object
|
---|
| 99 | isPlainObject(plainObject) // returns true
|
---|
| 100 | isAnyObject(plainObject) // returns true
|
---|
| 101 | getType(plainObject) // returns 'Object'
|
---|
| 102 |
|
---|
| 103 | // check the special object
|
---|
| 104 | isPlainObject(specialObject) // returns false !!!!!!!!!
|
---|
| 105 | isAnyObject(specialObject) // returns true
|
---|
| 106 | getType(specialObject) // returns 'Object'
|
---|
| 107 | ```
|
---|
| 108 |
|
---|
| 109 | > Please note that `isPlainObject` will only return `true` for normal plain JavaScript objects.
|
---|
| 110 |
|
---|
| 111 | ## TypeScript
|
---|
| 112 |
|
---|
| 113 | is-what makes TypeScript know the type during if statements. This means that a check returns the type of the payload for TypeScript users.
|
---|
| 114 |
|
---|
| 115 | ```ts
|
---|
| 116 | function isNumber (payload: any): payload is number {
|
---|
| 117 | // return boolean
|
---|
| 118 | }
|
---|
| 119 | // As you can see above, all functions return a boolean for JavaScript, but pass the payload type to TypeScript.
|
---|
| 120 |
|
---|
| 121 | // usage example:
|
---|
| 122 | function fn (payload: string | number): number {
|
---|
| 123 | if (isNumber(payload)) {
|
---|
| 124 | // ↑ TypeScript already knows payload is a number here!
|
---|
| 125 | return payload
|
---|
| 126 | }
|
---|
| 127 | return 0
|
---|
| 128 | }
|
---|
| 129 | ```
|
---|
| 130 |
|
---|
| 131 | `isPlainObject` and `isAnyObject` with TypeScript will declare the payload to be an object type with any props:
|
---|
| 132 |
|
---|
| 133 | ```ts
|
---|
| 134 | function isPlainObject (payload: any): payload is {[key: string]: any}
|
---|
| 135 | function isAnyObject (payload: any): payload is {[key: string]: any}
|
---|
| 136 | // The reason to return `{[key: string]: any}` is to be able to do
|
---|
| 137 | if (isPlainObject(payload) && payload.id) return payload.id
|
---|
| 138 | // if isPlainObject() would return `payload is object` then it would give an error at `payload.id`
|
---|
| 139 | ```
|
---|
| 140 |
|
---|
| 141 | ### isObjectLike
|
---|
| 142 |
|
---|
| 143 | If you want more control over which kind of objects are allowed you can use `isObjectLike<T>`:
|
---|
| 144 |
|
---|
| 145 | ```ts
|
---|
| 146 | import { isObjectLike } from 'is-what'
|
---|
| 147 | // usage examples:
|
---|
| 148 | isObjectLike<{specificKey: string}>(payload)
|
---|
| 149 | isObjectLike<object>(payload)
|
---|
| 150 | // you can pass a specific type for TS to check on.
|
---|
| 151 | ```
|
---|
| 152 |
|
---|
| 153 | `isObjectLike<T>` works like this under the hood:
|
---|
| 154 |
|
---|
| 155 | ```ts
|
---|
| 156 | function isObjectLike<T extends object> (payload: any): payload is T {
|
---|
| 157 | return isAnyObject(payload)
|
---|
| 158 | }
|
---|
| 159 | ```
|
---|
| 160 |
|
---|
| 161 | ## Meet the family
|
---|
| 162 |
|
---|
| 163 | - [is-what 🙉](https://github.com/mesqueeb/is-what)
|
---|
| 164 | - [merge-anything 🥡](https://github.com/mesqueeb/merge-anything)
|
---|
| 165 | - [filter-anything ⚔️](https://github.com/mesqueeb/filter-anything)
|
---|
| 166 | - [find-and-replace-anything 🎣](https://github.com/mesqueeb/find-and-replace-anything)
|
---|
| 167 | - [compare-anything 🛰](https://github.com/mesqueeb/compare-anything)
|
---|
| 168 | - [copy-anything 🎭](https://github.com/mesqueeb/copy-anything)
|
---|
| 169 | - [flatten-anything 🏏](https://github.com/mesqueeb/flatten-anything)
|
---|
| 170 |
|
---|
| 171 | ## Source code
|
---|
| 172 |
|
---|
| 173 | It's litterally just these functions:
|
---|
| 174 |
|
---|
| 175 | ```js
|
---|
| 176 | function getType (payload) {
|
---|
| 177 | return Object.prototype.toString.call(payload).slice(8, -1)
|
---|
| 178 | }
|
---|
| 179 | function isUndefined (payload) {
|
---|
| 180 | return getType(payload) === 'Undefined'
|
---|
| 181 | }
|
---|
| 182 | function isString (payload) {
|
---|
| 183 | return getType(payload) === 'String'
|
---|
| 184 | }
|
---|
| 185 | function isAnyObject (payload) {
|
---|
| 186 | return getType(payload) === 'Object'
|
---|
| 187 | }
|
---|
| 188 | // etc...
|
---|
| 189 | ```
|
---|
| 190 |
|
---|
| 191 | See the full source code [here](https://github.com/mesqueeb/is-what/blob/master/src/index.ts).
|
---|