Ty(type-yes) 是个极简的 Javascript 类型判断库(A library for determining the datatype of Javascript variables)
npm install type-yes首先通过一个例子来认识下 Ty —— 方法的入参类型判断,如:
function func(value) { if( value 为 string 或 number 或 为空时 ) { ... } }判断方式:
// 方式一:常规版 typeof value === 'string' || typeof value === 'number' || value == null // 方式二:Lodash 版 _.isString(value) || _.isNumber(value) || _.isNil(value) // 方式三:Ty 版 Ty(value).str.num.nil.orTy 版的判断是最简单的!!!,但是也会让人有些疑惑——上述表达式:Ty(value).str.num.nil.or,它如何实现判断的?下面分析下:
-
判断参数:需要判断的量,可以是任意类型
-
类型标识符:类型的“符号”。str—— string,num —— number, nil —— null or undefined
-
逻辑运算符:最终逻辑运算方式。or —— 或运算
上述表达式可以简单理解为:
// 当 value = 123 [[value, 'str'], [value, 'num'], [value, 'nil']] =判断类型=> [false, true, false] =或运算=> true 到了这里,你大概已经了解 Ty 的逻辑符 or 的使用,除了 or , Ty 还有 is,not,and,nor,nand
逻辑”是“判断
// 常规 typeof value === 'number' // Ty Ty(value).num.is // Ty error, 当进行 is 判断时,如果判断参数(或判断标识符)输入多个值时,会报错 Ty(value01, value02).num.is // error Ty(value).num.str.is // error逻辑”否“判断, is 的取反
// 常规 typeof value != 'number' // Ty Ty(value).num.not // Ty error, 当进行 not 判断时,如果判断参数(或判断标识符)输入多个值时,会报错。与 is 判断相同逻辑”或“判断
// 常规 typeof value === 'string' || typeof value === 'number' // Ty Ty(value).str.num.or // 等价于: Ty(value, value).str.num.or // 参数会自动补全,所以这样写就“没必要”了逻辑”或非“判断, or 的取反
// 常规 !(typeof value === 'string' || typeof value === 'number') // Ty Ty(value).str.num.nor逻辑“与”判断
示例一:
// 常规 typeof value01 === 'string' && typeof value02 === 'number' // Ty Ty(value01, value02).str.num.and示例二:
// 常规 typeof value01 === 'string' && typeof value02 === 'string' // Ty Ty(value01, value02).str.and // 等价于: Ty(value01, value02).str.str.and // 标识符也会自动补全,所以这样写就“没必要”了逻辑“与非”判断,and 的取反
// 常规 !(typeof value01 === 'string' && typeof value02 === 'number') // Ty Ty(value01, value02).arr.num.nand上述的判断中,除了所有的逻辑操作符的使用方法,我还认识了 num、str 、nil 等类型标识符。在 Ty 中,类型标识符共有 60+,其中包括:简写类型标识符、特殊类型标识符和常规类型标识符,下面我们将一一介绍:
| 简写标识符 | 对应的常规标识类 | 实际类型 |
|---|---|---|
| obj | object | Object (这里的 object, 不包含 array 和 null ) |
| arr | array | Array |
| str | string | String |
| num | number | Number |
| bool | boolean | Boolean |
| undef | undefined | undefined |
| func | function | Function |
| 标识符 | 实际类型 |
|---|---|
| nil | null 或 undefined |
| empty | [] 或 {} |
| emptyobject | {} —— 没有任何属性的空对象 |
| emptyarray | [] —— 没有任何元素的空数组 |
| NaN | NaN |
| infinity | Infinity 无穷大 |
| primitive | 原始类型: null, undefined, boolean, number, bigint, string, symbol |
示例:
const isPrimitive = Ty(value).primitive.is // value = Symbol() const isEmpty = Ty(value).empty.is // value = []| 标识符 | 实际类型 |
|---|---|
| null | null (不包含 undefined) |
| undefined | undefined |
| boolean | Boolean |
| number | Number |
| string | String |
| bigint | BigInt |
| symbol | Symbol |
| object | Object (这里的 object, 不包含 array 和 null ) |
| array | Array |
| function | Function |
| promise | Promise |
| date | Date |
| regexp | RegExp |
| map | Map |
| set | Set |
| ......更多的请看附录 |
示例:
const isIterator = Ty(value).array.map.set.or cosnt isPrimitive = Ty(value).null.undefined.boolean.number.string.bigint.symbol.or如果已有的类型标识符不满足时, Ty 支持扩展,只要提供一个 TypeMatcher , 即类型匹配器:
type TypeMatcher<T extends string> = (parameter: any, typeFlag: T) => boolean;示例(ts):
import { Ty, TypeMatcher, TypeFlag, buildinTypeMatcher } from 'ty'; type MyType = 'element' | 'finite' | TypeFlag; // TypeFlag 是 Ty 的所有的类型标识符的一个联合类型 const typeMather: TypeMatcher<MyType> = (parameter, typeFlag) => { // parameter —— 判断参数, typeFlag —— 类型标识符 switch (typeFlag) { case 'element': return parameter instanceof Element; case 'finite': return Number.isFinite(parameter); default: return buildinTypeMatcher(parameter, typeFlag); // buildinTypeMatcher —— Ty 内置的类型匹配器 } }; const tty = new Ty(typeMather);使用效果(element 和 finite 会出现在拼写提示中):
Proxy 类型是难以判断的——Proxy 代理的对象是什么类型,proxy 实例就判定为相应的类型,如:
const arr = ['a', 'b', 'c']; const arrProxy = new Proxy(arr, {}); typeof arrProxy; // array Object.prototype.toString.call(arrProxy); // [object Array]Ty 中,继承 Proxy 实现了一个子类:IdentifiableProxy,这个子类的类型是可以判断的,如:
const arr = ['a', 'b', 'c']; const arrProxy = new IdentifiableProxy(arr, {}); Object.prototype.toString.call(arrProxy); // [object Proxy-Array] // 使用 Ty 判断 Ty(arrProxy).proxy.is; // true —— 做 proxy 判断时,arrProxy 判定为 proxy Ty(arrProxy).array.is; // true —— 做 array 判断时,arrProxy 判定为 array Ty(arrProxy).array.proxy.and; // true如何使用 Ty 实现下面这样一个类型判断:
typeof value01 === 'object' && typeof value02 != 'number'在 Ty 中,可以对单个类型标识符进行否运算:! + 类型标识符,如:
Ty(value01, value02).obj['!num'].and // 如: Ty({}, 123).obj['!num'].and // false Ty({}, 'abc').obj['!num'].and // true如何使用 Ty 实现下面这样一个类型判断:
typeof value01 === 'object' && (typeof value02 === 'number' || value02 == null)在 Ty 中,可以对单个类型标识符进行可为空运算:? + 类型标识符,如:
// Ty(value01, value02).obj['?num'].and // 如: Ty({}, 123).obj['?num'].and // true Ty({}, null).obj['?num'].and // true| 标识符 | 对应类型 |
|---|---|
| error | Error |
| reflect | Reflect |
| json | JSON |
| math | Math |
| int8array | Int8Array |
| uint8array | Uint8Array |
| uint8clampedarray | Uint8ClampedArray |
| int16array | Int16Array |
| uint16array | Uint16Array |
| int32array | Int32Array |
| uint32array | Uint32Array |
| bigint64array | BigInt64Array |
| biguint64array | BigUint64Array (en-US) |
| float32array | Float32Array |
| float64array | Float64Array |
| weakmap | WeakMap |
| weakset | WeakSet |
| arraybuffer | ArrayBuffer |
| atomics | Atomics |
| dataview | DataView |
| weakref | WeakRef |
| finalizationregistry | FinalizationRegistry (en-US) |
| iterator | Iterator |
| proxy | Proxy |
| intl | Intl |
| intl.collator | Intl.Collator |
| intl.datetimeformat | Intl.DateTimeFormat |
| intl.displaynames | Intl.DisplayNames |
| intl.listformat | Intl.ListFormat |
| intl.locale | Intl.Locale |
| intl.numberformat | Intl.NumberFormat |
| intl.pluralrules | Intl.PluralRules |
| intl.relativetimeformat | Intl.RelativeTimeFormat |
| intl.segmenter | Intl.Segmenter |
| global | node 环境下的 globalThis |
| window | window 环境下的 globalThis 或 window |

