is-what 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
package/.babelrc ADDED
@@ -0,0 +1,3 @@
1
+ {
2
+ "presets": ["env"]
3
+ }
package/.eslintignore ADDED
@@ -0,0 +1,9 @@
1
+ # don't ever lint node_modules
2
+ node_modules
3
+ # don't lint build output (make sure it's set to your correct build folder name)
4
+ dist
5
+ # don't lint nyc coverage output
6
+ coverage
7
+
8
+ test
9
+ .eslintrc.js
@@ -0,0 +1,12 @@
1
+ # These are supported funding model platforms
2
+
3
+ github: mesqueeb
4
+ patreon: # Replace with a single Patreon username
5
+ open_collective: # Replace with a single Open Collective username
6
+ ko_fi: # Replace with a single Ko-fi username
7
+ tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8
+ community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9
+ liberapay: # Replace with a single Liberapay username
10
+ issuehunt: # Replace with a single IssueHunt username
11
+ otechie: # Replace with a single Otechie username
12
+ custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
package/.prettierrc ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "printWidth": 100,
3
+ "tabWidth": 2,
4
+ "singleQuote": true,
5
+ "trailingComma": "es5",
6
+ "semi": false,
7
+ "bracketSpacing": true,
8
+ "quoteProps": "consistent"
9
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "editor.formatOnSave": true,
3
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
4
+ "editor.tabSize": 2, // make sure this is the same as .prettierrc
5
+ "editor.insertSpaces": true,
6
+ "files.insertFinalNewline": true,
7
+ "files.trimFinalNewlines": true,
8
+ "files.trimTrailingWhitespace": true
9
+ }
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Luca Ban - Mesqueeb
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,272 @@
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
+
17
+ - A simple way to check any kind of type (including non-primitives)
18
+ - Be able to check if an object is a plain object `{}` or a special object (like a class instance) ‼️
19
+ - Let TypeScript automatically know what type a value is when checking
20
+
21
+ And that's exactly what `is-what` is! (what a great wordplay 😃)
22
+
23
+ ## Usage
24
+
25
+ is-what is really easy to use, and most functions work just like you'd expect.
26
+
27
+ ```js
28
+ // import functions you want to use like so:
29
+ import { isString, isDate, isPlainObject } from 'is-what'
30
+ ```
31
+
32
+ 1. First I'll go over the simple functions available. Only `isNumber` and `isDate` have special treatment.
33
+ 2. After that I'll talk about working with Objects (plain objects vs class instances etc.).
34
+ 3. Lastly I'll talk about TypeScript implementation
35
+
36
+ ### Simple type check functions
37
+
38
+ ```js
39
+ // basics
40
+ isBoolean(true) // true
41
+ isBoolean(false) // true
42
+ isUndefined(undefined) // true
43
+ isNull(null) // true
44
+
45
+ // strings
46
+ isString('') // true
47
+ isEmptyString('') // true
48
+ isFullString('') // false
49
+
50
+ // numbers
51
+ isNumber(0) // true
52
+ isNumber('0') // false
53
+ isNumber(NaN) // false *
54
+ isPositiveNumber(1) // true
55
+ isNegativeNumber(-1) // true
56
+ // * see below for special NaN use cases!
57
+
58
+ // arrays
59
+ isArray([]) // true
60
+ isEmptyArray([]) // true
61
+ isFullArray([1]) // true
62
+
63
+ // objects
64
+ isPlainObject({}) // true *
65
+ isEmptyObject({}) // true
66
+ isFullObject({ a: 1 }) // true
67
+ // * see below for special object (& class instance) use cases!
68
+
69
+ // functions
70
+ isFunction(function () {}) // true
71
+ isFunction(() => {}) // true
72
+
73
+ // dates
74
+ isDate(new Date()) // true
75
+ isDate(new Date('invalid date')) // false
76
+
77
+ // maps & sets
78
+ isMap(new Map()) // true
79
+ isSet(new Set()) // true
80
+ isWeakMap(new WeakMap()) // true
81
+ isWeakSet(new WeakSet()) // true
82
+
83
+ // others
84
+ isRegExp(/\s/gi) // true
85
+ isSymbol(Symbol()) // true
86
+ isBlob(new Blob()) // true
87
+ isFile(new File([''], '', { type: 'text/html' })) // true
88
+ isError(new Error('')) // true
89
+ isPromise(new Promise((resolve) => {})) // true
90
+
91
+ // primitives
92
+ isPrimitive('') // true
93
+ // true for any of: boolean, null, undefined, number, string, symbol
94
+ ```
95
+
96
+ ### Let's talk about NaN
97
+
98
+ `isNaN` is a built-in JS Function but it really makes no sense:
99
+
100
+ ```js
101
+ // 1)
102
+ typeof NaN === 'number' // true
103
+ // 🤔 ("not a number" is a "number"...)
104
+
105
+ // 2)
106
+ isNaN('1') // false
107
+ // 🤔 the string '1' is not-"not a number"... so it's a number??
108
+
109
+ // 3)
110
+ isNaN('one') // true
111
+ // 🤔 'one' is NaN but `NaN === 'one'` is false...
112
+ ```
113
+
114
+ With is-what the way we treat NaN makes a little bit more sense:
115
+
116
+ ```js
117
+ import { isNumber, isNaNValue } from 'is-what'
118
+
119
+ // 1)
120
+ isNumber(NaN) // false!
121
+ // let's not treat NaN as a number
122
+
123
+ // 2)
124
+ isNaNValue('1') // false
125
+ // if it's not NaN, it's not NaN!!
126
+
127
+ // 3)
128
+ isNaNValue('one') // false
129
+ // if it's not NaN, it's not NaN!!
130
+
131
+ isNaNValue(NaN) // true
132
+ ```
133
+
134
+ ### isPlainObject vs isAnyObject
135
+
136
+ 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:
137
+
138
+ - `isPlainObject` will only return `true` on plain JavaScript objects and not on classes or others
139
+ - `isAnyObject` will be more loose and return `true` on regular objects, classes, etc.
140
+
141
+ ```js
142
+ // define a plain object
143
+ const plainObject = { hello: 'I am a good old object.' }
144
+
145
+ // define a special object
146
+ class SpecialObject {
147
+ constructor(somethingSpecial) {
148
+ this.speciality = somethingSpecial
149
+ }
150
+ }
151
+ const specialObject = new SpecialObject('I am a special object! I am a class instance!!!')
152
+
153
+ // check the plain object
154
+ isPlainObject(plainObject) // returns true
155
+ isAnyObject(plainObject) // returns true
156
+ getType(plainObject) // returns 'Object'
157
+
158
+ // check the special object
159
+ isPlainObject(specialObject) // returns false !!!!!!!!!
160
+ isAnyObject(specialObject) // returns true
161
+ getType(specialObject) // returns 'Object'
162
+ ```
163
+
164
+ > Please note that `isPlainObject` will only return `true` for normal plain JavaScript objects.
165
+
166
+ ### Getting and checking for specific types
167
+
168
+ You can check for specific types with `getType` and `isType`:
169
+
170
+ ```js
171
+ import { getType, isType } from 'is-what'
172
+
173
+ getType('') // returns 'String'
174
+ // pass a Type as second param:
175
+ isType('', String) // returns true
176
+ ```
177
+
178
+ ## TypeScript
179
+
180
+ is-what makes TypeScript know the type during if statements. This means that a check returns the type of the payload for TypeScript users.
181
+
182
+ ```ts
183
+ function isNumber(payload: any): payload is number {
184
+ // return boolean
185
+ }
186
+ // As you can see above, all functions return a boolean for JavaScript, but pass the payload type to TypeScript.
187
+
188
+ // usage example:
189
+ function fn(payload: string | number): number {
190
+ if (isNumber(payload)) {
191
+ // ↑ TypeScript already knows payload is a number here!
192
+ return payload
193
+ }
194
+ return 0
195
+ }
196
+ ```
197
+
198
+ `isPlainObject` and `isAnyObject` with TypeScript will declare the payload to be an object type with any props:
199
+
200
+ ```ts
201
+ function isPlainObject(payload: any): payload is { [key: string]: any }
202
+ function isAnyObject(payload: any): payload is { [key: string]: any }
203
+ // The reason to return `{[key: string]: any}` is to be able to do
204
+ if (isPlainObject(payload) && payload.id) return payload.id
205
+ // if isPlainObject() would return `payload is object` then it would give an error at `payload.id`
206
+ ```
207
+
208
+ ### isObjectLike
209
+
210
+ If you want more control over what kind of interface/type is casted when checking for objects.
211
+
212
+ To cast to a specific type while checking for `isAnyObject`, can use `isObjectLike<T>`:
213
+
214
+ ```ts
215
+ import { isObjectLike } from 'is-what'
216
+
217
+ const payload = { name: 'Mesqueeb' } // current type: `{ name: string }`
218
+
219
+ // Without casting:
220
+ if (isAnyObject(payload)) {
221
+ // in here `payload` is casted to: `Record<string | number | symbol, any>`
222
+ // WE LOOSE THE TYPE!
223
+ }
224
+
225
+ // With casting:
226
+ // you can pass a specific type for TS that will be casted when the function returns
227
+ if (isObjectLike<{ name: string }>(payload)) {
228
+ // in here `payload` is casted to: `{ name: string }`
229
+ }
230
+ ```
231
+
232
+ Please note: this library will not actually check the shape of the object, you need to do that yourself.
233
+
234
+ `isObjectLike<T>` works like this under the hood:
235
+
236
+ ```ts
237
+ function isObjectLike<T extends object>(payload: any): payload is T {
238
+ return isAnyObject(payload)
239
+ }
240
+ ```
241
+
242
+ ## Meet the family
243
+
244
+ - [is-what 🙉](https://github.com/mesqueeb/is-what)
245
+ - [merge-anything 🥡](https://github.com/mesqueeb/merge-anything)
246
+ - [filter-anything ⚔️](https://github.com/mesqueeb/filter-anything)
247
+ - [find-and-replace-anything 🎣](https://github.com/mesqueeb/find-and-replace-anything)
248
+ - [compare-anything 🛰](https://github.com/mesqueeb/compare-anything)
249
+ - [copy-anything 🎭](https://github.com/mesqueeb/copy-anything)
250
+ - [flatten-anything 🏏](https://github.com/mesqueeb/flatten-anything)
251
+
252
+ ## Source code
253
+
254
+ It's litterally just these functions:
255
+
256
+ ```js
257
+ function getType(payload) {
258
+ return Object.prototype.toString.call(payload).slice(8, -1)
259
+ }
260
+ function isUndefined(payload) {
261
+ return getType(payload) === 'Undefined'
262
+ }
263
+ function isString(payload) {
264
+ return getType(payload) === 'String'
265
+ }
266
+ function isAnyObject(payload) {
267
+ return getType(payload) === 'Object'
268
+ }
269
+ // etc...
270
+ ```
271
+
272
+ See the full source code [here](https://github.com/mesqueeb/is-what/blob/master/src/index.ts).
package/build.js ADDED
@@ -0,0 +1,40 @@
1
+ /* eslint-disable */
2
+
3
+ // npm i -D rollup rollup-plugin-typescript2 typescript
4
+ import typescript from 'rollup-plugin-typescript2'
5
+
6
+ // ------------------------------------------------------------------------------------------
7
+ // formats
8
+ // ------------------------------------------------------------------------------------------
9
+ // amd – Asynchronous Module Definition, used with module loaders like RequireJS
10
+ // cjs – CommonJS, suitable for Node and Browserify/Webpack
11
+ // esm – Keep the bundle as an ES module file
12
+ // iife – A self-executing function, suitable for inclusion as a <script> tag. (If you want to create a bundle for your application, you probably want to use this, because it leads to smaller file sizes.)
13
+ // umd – Universal Module Definition, works as amd, cjs and iife all in one
14
+ // system – Native format of the SystemJS loader
15
+
16
+ // ------------------------------------------------------------------------------------------
17
+ // setup
18
+ // ------------------------------------------------------------------------------------------
19
+ const pkg = require('./package.json')
20
+ const name = pkg.name
21
+ const className = name.replace(/(^\w|-\w)/g, (c) => c.replace('-', '').toUpperCase())
22
+
23
+ export default [
24
+ {
25
+ input: 'src/index.ts',
26
+ output: [
27
+ {
28
+ file: 'dist/index.js',
29
+ format: 'esm',
30
+ sourcemap: false,
31
+ name: className,
32
+ exports: 'named',
33
+ },
34
+ ],
35
+ plugins: [
36
+ typescript({ useTsconfigDeclarationDir: true, tsconfigOverride: { exclude: ['test/**/*'] } }),
37
+ ],
38
+ external: Object.keys(pkg.dependencies || []),
39
+ },
40
+ ]