/*
* @Description: 数据类型判断
* @Author: huhaonan@sics.ac.cn
* @Date: 2021-12-10 17:24:17
* @LastEditors: huhaonan@sics.ac.cn
* @LastEditTime: 2022-01-07 10:45:21
*/
const toString = Object.prototype.toString
export function isType(value: unknown, type: string) {
return toString.call(value) === `[object ${type}]`
}
// 提取数据原始类型
export function getType(value: unknown): string {
return toString
.call(value)
.replace(/^\[object /, '')
.replace(/]$/, '')
}
// 提取数据原始类型
const toRawType = (value) => {
return Object.prototype.toString.call(value).slice(8, -1)
} // 示例 toRawType(''); 'String' toRawType([]); 'Array'
// 是否为原始数据类型
export function isPrimitive(value: unknown) {
return (
typeof value === 'string' ||
typeof value === 'number' ||
// $flow-disable-line
typeof value === 'symbol' ||
typeof value === 'boolean'
)
}
export function isNull(value: unknown): value is null {
return value === null
}
export function isDef<T = unknown>(value?: T): value is T {
return typeof value !== 'undefined'
}
export function isUndefined<T = unknown>(value?: T): value is T {
return value === undefined
}
export function isNil(value: any): value is null | undefined {
/**
* isNil(null) => true
* isNil() => true
*/
return value === null || value === undefined
}
export function isNullAndUnDef(value: unknown): value is null | undefined {
return isUndefined(value) && isNull(value)
}
export function isNullOrUnDef(value: unknown): value is null | undefined {
return isUndefined(value) || isNull(value)
}
export function isBoolean(value: unknown): value is boolean {
return isType(value, 'Boolean')
}
export function isNumber(value: unknown): value is number {
return isType(value, 'Number')
}
//是否整数
export const isInteger = Number.isInteger
? Number.isInteger
: function (num: any): boolean {
return isNumber(num) && num % 1 === 0
}
// 是否正数
export function isPositive(num: any): boolean {
return isNumber(num) && num > 0
}
// 是否负数
export function isNegative(num: unknown): boolean {
return isNumber(num) && num < 0
}
// 是否偶数
export function isEven(num: unknown): boolean {
return isNumber(num) && num % 2 === 0
}
// 是否奇数
export function isOdd(num: any): boolean {
return isNumber(num) && num % 2 !== 0
}
export function isDecimal(num: any): boolean {
return isNumber(num) && num % 1 !== 0
}
export function isString(value: unknown): value is string {
return isType(value, 'String')
}
// isIntegerKey 判断是不是数字型的字符串
export const isIntegerKey = (key) => isString(key) &&
key !== 'NaN' &&
key[0] !== '-' && '' + parseInt(key, 10) === key;
// 例子:
// isIntegerKey('a'); // false
// isIntegerKey('0'); // true
// isIntegerKey('011'); // false
// isIntegerKey('11'); // true
// isIntegerKey('-11'); // false
// isIntegerKey(11); // false
// isIntegerKey('NaN'); // false
// 引用数据类型
export function isArray(value: any): value is Array<any> {
return value && Array.isArray(value)
}
// 是否类数组结构
export function isArrayLike(value: any): boolean {
/**
* isArrayLike([1, 2, 3]) => true
* isArrayLike(document.body.children) => true
* isArrayLike('abc') => true
* isArrayLike(Function) => false
*/
return value !== null && typeof value !== 'function' && isFinite(value.length)
}
export interface ObjectType<T> {
[key: string]: T
}
// export function isObject(value: any): value is Record<any, any> {
// return value !== null && isType(value, 'Object')
// }
export function isObject<T = any>(value: any): value is T {
/**
* isObject({}) => true
* isObject([1, 2, 3]) => true
* isObject(Function) => true
* isObject(null) => false
*/
const type = typeof value
return (value !== null && type === 'object') || type === 'function'
}
export function isObjectLike(value: any): value is ObjectType<any> {
/**
* isObjectLike({}) => true
* isObjectLike([1, 2, 3]) => true
* isObjectLike(Function) => false
* isObjectLike(null) => false
*/
return value !== null && typeof value === 'object'
}
export function isPrototype(value: any): boolean {
const Ctor = value && value.constructor
const proto =
(typeof Ctor === 'function' && Ctor.prototype) || Object.prototype
return value === proto
}
export function isFunction(value: unknown) {
return typeof value === 'function'
}
/**
* 是否是参数类型
*
* @param {Object} value 测试的值
* @return {Boolean}
*/
export function isArguments(value: any): boolean {
return isType(value, 'Arguments')
}
// export function isEmpty<T = unknown>(value: T): value is T {
// if (isArray(value) || isString(value)) {
// return value.length === 0
// }
// if (value instanceof Map || value instanceof Set) {
// return value.size === 0
// }
// if (isObject(value)) {
// return Object.keys(value).length === 0
// }
// return false
// }
/**
* @Description: 是否为空
* @param {any} value
*/
export function isEmpty(value: any): boolean {
/**
* isEmpty(null) => true
* isEmpty() => true
* isEmpty(true) => true
* isEmpty(1) => true
* isEmpty([1, 2, 3]) => false
* isEmpty('abc') => false
* isEmpty({ a: 1 }) => false
*/
const hasOwnProperty = Object.prototype.hasOwnProperty
if (isNil(value)) {
return true
}
if (isArrayLike(value)) {
return !value.length
}
const type = getType(value)
if (type === 'Map' || type === 'Set') {
return !value.size
}
if (isPrototype(value)) {
return !Object.keys(value).length
}
for (const key in value) {
if (hasOwnProperty.call(value, key)) {
return false
}
}
return true
}
export function isRegExp(value: unknown): value is RegExp {
return isType(value, 'RegExp')
}
export function isDate(value: unknown): value is Date {
return isType(value, 'Date')
}
export function isFormData(val: unknown) {
return typeof FormData !== 'undefined' && val instanceof FormData
}
export function isPromise<T = any>(value: unknown): value is Promise<T> {
return (
isType(value, 'Promise') &&
isObject(value) &&
isFunction(value.then) &&
isFunction(value.catch)
)
}
export function isError(value: any): value is Error {
return isType(value, 'Error')
}
/**
* @Description: 两个数据是否相同
* @param {any} value
* @param {any} other
*/
export function isEqual(value: any, other: any): boolean {
if (value === other) {
return true
}
if (!value || !other) {
return false
}
if (isString(value) || isString(other)) {
return false
}
if (isArrayLike(value) || isArrayLike(other)) {
if (value.length !== other.length) {
return false
}
let rst = true
for (let i = 0; i < value.length; i++) {
rst = isEqual(value[i], other[i])
if (!rst) {
break
}
}
return rst
}
if (isObjectLike(value) || isObjectLike(other)) {
const valueKeys = Object.keys(value)
const otherKeys = Object.keys(other)
if (valueKeys.length !== otherKeys.length) {
return false
}
let rst = true
for (let i = 0; i < valueKeys.length; i++) {
rst = isEqual(value[valueKeys[i]], other[valueKeys[i]])
if (!rst) {
break
}
}
return rst
}
return false
}
/**
* @Description: 两个数据是否相同,不依赖其他函数,来自https://www.30secondsofcode.org/js/s/equals/
* @param {any} value
* @param {any} other
*/
const equals = (a: any, b: any): boolean => {
if (a === b) return true;
if (a instanceof Date && b instanceof Date)
return a.getTime() === b.getTime();
if (!a || !b || (typeof a !== "object" && typeof b !== "object"))
return a === b;
if (a.prototype !== b.prototype) return false;
const keys = Object.keys(a);
if (keys.length !== Object.keys(b).length) return false;
return keys.every((k) => equals(a[k], b[k]));
};
export function isWindow(value: any): value is Window {
return typeof window !== 'undefined' && isType(value, 'Window')
}
// export function isElement(value: unknown): value is Element {
// return isObject(value) && !!value.tagName
// }
/**
* 判断是否HTML元素
* @return {Boolean} 是否HTML元素
*/
export function isElement(o: any): boolean {
return o instanceof Element || o instanceof HTMLDocument
}
export const isServer = typeof window === 'undefined'
export const isClient = !isServer
export function isUrl(path: string): boolean {
const reg =
/(((^https?:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)$/
return reg.test(path)
}