npm i type-yes
项目地址:https://github.com/liutaigang/type-yes
🚀 About
首先通过一个例子来认识下 Ty —— 方法的参数类型判断,如:
function func(value) {
if( value 为 string 或 number 或 为空 ) {
... do something
}
}
判断方式:
// 方式一:常规版
typeof value === 'string' || typeof value === 'number' || value == null
// 方式二:Lodash 版
_.isString(value) || _.isNumber(value) || _.isNil(value)
// 方式三:Ty 版
Ty(value).str.num.nil.or
Ty 版的判断是最简洁的!!!,但是也会让人有些疑惑——上述表达式: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
🦄 Usage
is
逻辑”是“判断
// 常规
typeof value === 'number'
// Ty
Ty(value).num.is
// Ty error, 当进行 is 判断时,如果判断参数(或判断标识符)输入多个值时,会报错
Ty(value01, value02).num.is // error
Ty(value).num.str.is // error
not
逻辑”否“判断, is 的取反
// 常规
typeof value != 'number'
// Ty
Ty(value).num.not
// Ty error, 当进行 not 判断时,如果判断参数(或判断标识符)输入多个值时,会报错。与 is 判断相同
or
逻辑”或“判断
// 常规
typeof value === 'string' || typeof value === 'number'
// Ty
Ty(value).str.num.or
// 等价于:
Ty(value, value).str.num.or // 参数会自动补全,所以这样写就“没必要”了
nor
逻辑”或非“判断, or 的取反
// 常规
!(typeof value === 'string' || typeof value === 'number')
// Ty
Ty(value).str.num.nor
and
逻辑“与”判断
示例一:
// 常规
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 // 标识符也会自动补全,所以这样写就“没必要”了
nand
逻辑“与非”判断,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 |
示例:
// value = Symbol()
const isPrimitive = Ty(value).primitive.is // true
// value = []
const isEmpty = Ty(value).empty.is //true
常规类型标识符
标识符 | 实际类型 |
---|---|
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 |
…更多的请看附录 |
示例:
// value = new Map()
const isIterator = Ty(value).array.map.set.or // true
// value = 123123123n
cosnt isPrimitive = Ty(value).number.string.bigint.symbol.or // true
🔩 More
扩展的 Ty 的类型标识符
如果已有的类型标识符不满足时, Ty 支持扩展,只要提供一个 TypeMatcher , 即类型匹配器:
type TypeMatcher<T extends string> = (parameter: any, typeFlag: T) => boolean;
示例(ts):
import { Ty, TypeMatcher, TypeFlag, buildinTypeMatcher } from 'type-yes';
type MyType = 'obj_arr_null' | 'finite' | TypeFlag; // TypeFlag 是 Ty 的所有的类型标识符的一个联合类型
const typeMatcher: TypeMatcher<MyType> = (parameter, typeFlag) => { // parameter —— 判断参数, typeFlag —— 类型标识符
switch (typeFlag) {
case 'obj_arr_null':
return typeof parameter == null;
case 'finite':
return Number.isFinite(parameter);
default:
return buildinTypeMatcher(parameter, typeFlag); // buildinTypeMatcher —— Ty 内置的类型匹配器
}
};
const tty = new Ty(typeMatcher);
tty({}).obj_arr_null.is; // true
tty([]).obj_arr_null.is; // true
tty(null).obj_arr_null.is; // true
tty(123).finite.is; // true
使用效果(obj_arr_null 和 finite 会出现在拼写提示中):
Proxy 如何判断
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
🍩 Appendix
常规类型标识符附录
标识符 | 对应类型 |
---|---|
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 |