• Stars
    star
    170
  • Rank 223,357 (Top 5 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created over 6 years ago
  • Updated 5 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

JS type check (TypeScript supported) functions like `isPlainObject() isArray()` etc. A simple & small integration.

is What? ๐Ÿ™‰

Total Downloads Latest Stable Version

Very simple & small JS type check functions. It's fully TypeScript supported!

npm i is-what

Or for deno available at: "deno.land/x/is_what"

Also check out is-where ๐Ÿ™ˆ

Motivation

I built is-what because the existing solutions were all too complex or too poorly built.

I was looking for:

  • A simple way to check any kind of type (including non-primitives)
  • Be able to check if an object is a plain object {} or a special object (like a class instance) โ€ผ๏ธ
  • Let TypeScript automatically know what type a value is when checking

And that's exactly what is-what is! (what a great wordplay ๐Ÿ˜ƒ)

Usage

is-what is really easy to use, and most functions work just like you'd expect.

// import functions you want to use like so:
import { isString, isDate, isPlainObject } from 'is-what'
  1. First I'll go over the simple functions available. Only isNumber and isDate have special treatment.
  2. After that I'll talk about working with Objects (plain objects vs class instances etc.).
  3. Lastly I'll talk about TypeScript implementation

Simple type check functions

// basics
isBoolean(true) // true
isBoolean(false) // true
isUndefined(undefined) // true
isNull(null) // true

// strings
isString('') // true
isEmptyString('') // true
isFullString('') // false

// numbers
isNumber(0) // true
isNumber('0') // false
isNumber(NaN) // false *
isPositiveNumber(1) // true
isNegativeNumber(-1) // true
// * see below for special NaN use cases!

// arrays
isArray([]) // true
isEmptyArray([]) // true
isFullArray([1]) // true

// objects
isPlainObject({}) // true *
isEmptyObject({}) // true
isFullObject({ a: 1 }) // true
// * see below for special object (& class instance) use cases!

// functions
isFunction(function () {}) // true
isFunction(() => {}) // true

// dates
isDate(new Date()) // true
isDate(new Date('invalid date')) // false

// maps & sets
isMap(new Map()) // true
isSet(new Set()) // true
isWeakMap(new WeakMap()) // true
isWeakSet(new WeakSet()) // true

// others
isRegExp(/\s/gi) // true
isSymbol(Symbol()) // true
isBlob(new Blob()) // true
isFile(new File([''], '', { type: 'text/html' })) // true
isError(new Error('')) // true
isPromise(new Promise((resolve) => {})) // true

// primitives
isPrimitive('') // true
// true for any of: boolean, null, undefined, number, string, symbol

Let's talk about NaN

isNaN is a built-in JS Function but it really makes no sense:

// 1)
typeof NaN === 'number' // true
// ๐Ÿค” ("not a number" is a "number"...)

// 2)
isNaN('1') // false
// ๐Ÿค” the string '1' is not-"not a number"... so it's a number??

// 3)
isNaN('one') // true
// ๐Ÿค” 'one' is NaN but `NaN === 'one'` is false...

With is-what the way we treat NaN makes a little bit more sense:

import { isNumber, isNaNValue } from 'is-what'

// 1)
isNumber(NaN) // false!
// let's not treat NaN as a number

// 2)
isNaNValue('1') // false
// if it's not NaN, it's not NaN!!

// 3)
isNaNValue('one') // false
// if it's not NaN, it's not NaN!!

isNaNValue(NaN) // true

isPlainObject vs isAnyObject

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:

  • isPlainObject will only return true on plain JavaScript objects and not on classes or others
  • isAnyObject will be more loose and return true on regular objects, classes, etc.
// define a plain object
const plainObject = { hello: 'I am a good old object.' }

// define a special object
class SpecialObject {
  constructor(somethingSpecial) {
    this.speciality = somethingSpecial
  }
}
const specialObject = new SpecialObject('I am a special object! I am a class instance!!!')

// check the plain object
isPlainObject(plainObject) // returns true
isAnyObject(plainObject) // returns true
getType(plainObject) // returns 'Object'

// check the special object
isPlainObject(specialObject) // returns false !!!!!!!!!
isAnyObject(specialObject) // returns true
getType(specialObject) // returns 'Object'

Please note that isPlainObject will only return true for normal plain JavaScript objects.

Getting and checking for specific types

You can check for specific types with getType and isType:

import { getType, isType } from 'is-what'

getType('') // returns 'String'
// pass a Type as second param:
isType('', String) // returns true

If you just want to make sure your object inherits from a particular class or toStringTag value, you can use isInstanceOf() like this:

import { isInstanceOf } from 'is-what'

isInstanceOf(new XMLHttpRequest(), 'EventTarget')
// returns true
isInstanceOf(globalThis, ReadableStream)
// returns false

TypeScript

is-what makes TypeScript know the type during if statements. This means that a check returns the type of the payload for TypeScript users.

function isNumber(payload: any): payload is number {
  // return boolean
}
// As you can see above, all functions return a boolean for JavaScript, but pass the payload type to TypeScript.

// usage example:
function fn(payload: string | number): number {
  if (isNumber(payload)) {
    // โ†‘ TypeScript already knows payload is a number here!
    return payload
  }
  return 0
}

isPlainObject and isAnyObject with TypeScript will declare the payload to be an object type with any props:

function isPlainObject(payload: any): payload is { [key: string]: any }
function isAnyObject(payload: any): payload is { [key: string]: any }
// The reason to return `{[key: string]: any}` is to be able to do
if (isPlainObject(payload) && payload.id) return payload.id
// if isPlainObject() would return `payload is object` then it would give an error at `payload.id`

isObjectLike

If you want more control over what kind of interface/type is casted when checking for objects.

To cast to a specific type while checking for isAnyObject, can use isObjectLike<T>:

import { isObjectLike } from 'is-what'

const payload = { name: 'Mesqueeb' } // current type: `{ name: string }`

// Without casting:
if (isAnyObject(payload)) {
  // in here `payload` is casted to: `Record<string | number | symbol, any>`
  // WE LOOSE THE TYPE!
}

// With casting:
// you can pass a specific type for TS that will be casted when the function returns
if (isObjectLike<{ name: string }>(payload)) {
  // in here `payload` is casted to: `{ name: string }`
}

Please note: this library will not actually check the shape of the object, you need to do that yourself.

isObjectLike<T> works like this under the hood:

function isObjectLike<T extends object>(payload: any): payload is T {
  return isAnyObject(payload)
}

Meet the family (more tiny utils with TS support)

Source code

It's litterally just these functions:

function getType(payload) {
  return Object.prototype.toString.call(payload).slice(8, -1)
}
function isUndefined(payload) {
  return getType(payload) === 'Undefined'
}
function isString(payload) {
  return getType(payload) === 'String'
}
function isAnyObject(payload) {
  return getType(payload) === 'Object'
}
// etc...

See the full source code here.

More Repositories

1

merge-anything

Merge objects & other types recursively. A simple & small integration.
TypeScript
336
star
2

vuex-easy-firestore

Easy coupling of firestore and a vuex module. 2-way sync with 0 boilerplate!
JavaScript
234
star
3

case-anything

camelCase, kebab-case, PascalCase... a simple integration with nano package size. (SMALL footprint!)
TypeScript
92
star
4

vuex-easy-access

Unified syntax for accessing your Vuex store through simple set() and get() functions + auto generate mutations
JavaScript
52
star
5

quasar-app-extension-draggable

A Quasar extension that makes elements draggable and movable with keyboard.
Vue
48
star
6

copy-anything

An optimised way to copy'ing (cloning) an Object or Array. A small and simple integration
TypeScript
40
star
7

filter-anything

A simple (TypeScript) integration of "pick" and "omit" to filter props of an object
TypeScript
31
star
8

quasar-ui-easy-forms

A Quasar extension to easily generate forms by only defining a "schema" object.
JavaScript
31
star
9

quasar-app-extension-swipe-to-close

A Quasar extension that allows you to close dialogs by swiping.
Vue
29
star
10

flatten-anything

Flatten objects and replace nested props with 'prop.subprop'. A simple and small integration.
TypeScript
25
star
11

find-and-replace-anything

Replace one val with another or all occurrences in an object recursively. A simple & small integration.
TypeScript
21
star
12

is-where

JS environment check functions like `isWebkit() isSafari() isBrowser() isNode()` etc. A simple & small integration.
TypeScript
19
star
13

quasar-ui-easy-tables

JavaScript
10
star
14

vuex-easy-firestore-sample-app

This is a sample app for vuex-easy-firestore
Vue
9
star
15

compare-anything

Compares objects and tells you which props are duplicate, and props are only present once.
TypeScript
9
star
16

remove-anything

An optimised way to remove any prop value (eg. undefined, empty objects, ...) from an object. A small and simple integration
TypeScript
8
star
17

map-anything

Array.map but for objects with good TypeScript support. A small and simple integration.
TypeScript
7
star
18

getorset-anything

Gets a value from a Map/Obj or sets an initial value when not found and returns that. TypeScript supported.
TypeScript
7
star
19

nestify-anything

Recreates an object from any `nested.props`. A simple and small integration.
TypeScript
5
star
20

check-anything

Checks anything from URLs to email addresses. A small and simple integration.
TypeScript
4
star
21

SwiftDataSugar

๐ŸŒฏ A collection of utilities that make it easier to work with SwiftData in a SwiftUI environment
Swift
4
star
22

sha-anything

A tiny TS utility to sha256 anything, including objects
TypeScript
3
star
23

SwiftVsTypeScript

A cheatsheet for those dabbling in both languages ๐Ÿ‘๐Ÿป
Vue
3
star
24

quasar-app-extension-draggable-demo

Demo for: A Quasar extension that makes elements draggable and movable with keyboard.
Vue
2
star
25

lucaban.com

Portal website lucaban.com
JavaScript
2
star
26

JustSugar

๐Ÿฐ JS-inspired Syntax Sugar on top of Swift to make working with Arrays/Strings/... easier
Swift
2
star
27

CaseAnything

๐Ÿซ Swift Case Conversions โ€” camelCase PascalCase UpperCamelCase kebab-case snake_case CONSTANT_CASE Train-Case Ada_Case COBOL-CASE Dot.notation Path/case Space case Capital Case lower case UPPER CASE
Swift
2
star
28

commafy-anything

Return a number as string with , or K. A simple and small integration
TypeScript
2
star
29

roll-anything

This is a very tiny dice util. ๐ŸŽฒ You can roll a dice with any amount of sides.
TypeScript
1
star
30

path-to-prop

Retrieves a property from an object based on a path.to.that.prop
TypeScript
1
star
31

MicroMaxOnAppleSilicon

โ™Ÿ๏ธ The ยต-Max C Chess engine to play Chess games. Built as multi-platform Swift Package for iOS, visionOS, macOS
C++
1
star
32

SwiftStringCatalogsPOC

A proof of concept that combines the String Catalog of a Swift Package together with a host app's.
Swift
1
star