1. /*
    2. * @Description: 数据类型判断
    3. * @Author: huhaonan@sics.ac.cn
    4. * @Date: 2021-12-10 17:24:17
    5. * @LastEditors: huhaonan@sics.ac.cn
    6. * @LastEditTime: 2022-01-07 10:45:21
    7. */
    8. const toString = Object.prototype.toString
    9. export function isType(value: unknown, type: string) {
    10. return toString.call(value) === `[object ${type}]`
    11. }
    12. // 提取数据原始类型
    13. export function getType(value: unknown): string {
    14. return toString
    15. .call(value)
    16. .replace(/^\[object /, '')
    17. .replace(/]$/, '')
    18. }
    19. // 提取数据原始类型
    20. const toRawType = (value) => {
    21. return Object.prototype.toString.call(value).slice(8, -1)
    22. } // 示例 toRawType(''); 'String' toRawType([]); 'Array'
    23. // 是否为原始数据类型
    24. export function isPrimitive(value: unknown) {
    25. return (
    26. typeof value === 'string' ||
    27. typeof value === 'number' ||
    28. // $flow-disable-line
    29. typeof value === 'symbol' ||
    30. typeof value === 'boolean'
    31. )
    32. }
    33. export function isNull(value: unknown): value is null {
    34. return value === null
    35. }
    36. export function isDef<T = unknown>(value?: T): value is T {
    37. return typeof value !== 'undefined'
    38. }
    39. export function isUndefined<T = unknown>(value?: T): value is T {
    40. return value === undefined
    41. }
    42. export function isNil(value: any): value is null | undefined {
    43. /**
    44. * isNil(null) => true
    45. * isNil() => true
    46. */
    47. return value === null || value === undefined
    48. }
    49. export function isNullAndUnDef(value: unknown): value is null | undefined {
    50. return isUndefined(value) && isNull(value)
    51. }
    52. export function isNullOrUnDef(value: unknown): value is null | undefined {
    53. return isUndefined(value) || isNull(value)
    54. }
    55. export function isBoolean(value: unknown): value is boolean {
    56. return isType(value, 'Boolean')
    57. }
    58. export function isNumber(value: unknown): value is number {
    59. return isType(value, 'Number')
    60. }
    61. //是否整数
    62. export const isInteger = Number.isInteger
    63. ? Number.isInteger
    64. : function (num: any): boolean {
    65. return isNumber(num) && num % 1 === 0
    66. }
    67. // 是否正数
    68. export function isPositive(num: any): boolean {
    69. return isNumber(num) && num > 0
    70. }
    71. // 是否负数
    72. export function isNegative(num: unknown): boolean {
    73. return isNumber(num) && num < 0
    74. }
    75. // 是否偶数
    76. export function isEven(num: unknown): boolean {
    77. return isNumber(num) && num % 2 === 0
    78. }
    79. // 是否奇数
    80. export function isOdd(num: any): boolean {
    81. return isNumber(num) && num % 2 !== 0
    82. }
    83. export function isDecimal(num: any): boolean {
    84. return isNumber(num) && num % 1 !== 0
    85. }
    86. export function isString(value: unknown): value is string {
    87. return isType(value, 'String')
    88. }
    89. // isIntegerKey 判断是不是数字型的字符串
    90. export const isIntegerKey = (key) => isString(key) &&
    91. key !== 'NaN' &&
    92. key[0] !== '-' && '' + parseInt(key, 10) === key;
    93. // 例子:
    94. // isIntegerKey('a'); // false
    95. // isIntegerKey('0'); // true
    96. // isIntegerKey('011'); // false
    97. // isIntegerKey('11'); // true
    98. // isIntegerKey('-11'); // false
    99. // isIntegerKey(11); // false
    100. // isIntegerKey('NaN'); // false
    101. // 引用数据类型
    102. export function isArray(value: any): value is Array<any> {
    103. return value && Array.isArray(value)
    104. }
    105. // 是否类数组结构
    106. export function isArrayLike(value: any): boolean {
    107. /**
    108. * isArrayLike([1, 2, 3]) => true
    109. * isArrayLike(document.body.children) => true
    110. * isArrayLike('abc') => true
    111. * isArrayLike(Function) => false
    112. */
    113. return value !== null && typeof value !== 'function' && isFinite(value.length)
    114. }
    115. export interface ObjectType<T> {
    116. [key: string]: T
    117. }
    118. // export function isObject(value: any): value is Record<any, any> {
    119. // return value !== null && isType(value, 'Object')
    120. // }
    121. export function isObject<T = any>(value: any): value is T {
    122. /**
    123. * isObject({}) => true
    124. * isObject([1, 2, 3]) => true
    125. * isObject(Function) => true
    126. * isObject(null) => false
    127. */
    128. const type = typeof value
    129. return (value !== null && type === 'object') || type === 'function'
    130. }
    131. export function isObjectLike(value: any): value is ObjectType<any> {
    132. /**
    133. * isObjectLike({}) => true
    134. * isObjectLike([1, 2, 3]) => true
    135. * isObjectLike(Function) => false
    136. * isObjectLike(null) => false
    137. */
    138. return value !== null && typeof value === 'object'
    139. }
    140. export function isPrototype(value: any): boolean {
    141. const Ctor = value && value.constructor
    142. const proto =
    143. (typeof Ctor === 'function' && Ctor.prototype) || Object.prototype
    144. return value === proto
    145. }
    146. export function isFunction(value: unknown) {
    147. return typeof value === 'function'
    148. }
    149. /**
    150. * 是否是参数类型
    151. *
    152. * @param {Object} value 测试的值
    153. * @return {Boolean}
    154. */
    155. export function isArguments(value: any): boolean {
    156. return isType(value, 'Arguments')
    157. }
    158. // export function isEmpty<T = unknown>(value: T): value is T {
    159. // if (isArray(value) || isString(value)) {
    160. // return value.length === 0
    161. // }
    162. // if (value instanceof Map || value instanceof Set) {
    163. // return value.size === 0
    164. // }
    165. // if (isObject(value)) {
    166. // return Object.keys(value).length === 0
    167. // }
    168. // return false
    169. // }
    170. /**
    171. * @Description: 是否为空
    172. * @param {any} value
    173. */
    174. export function isEmpty(value: any): boolean {
    175. /**
    176. * isEmpty(null) => true
    177. * isEmpty() => true
    178. * isEmpty(true) => true
    179. * isEmpty(1) => true
    180. * isEmpty([1, 2, 3]) => false
    181. * isEmpty('abc') => false
    182. * isEmpty({ a: 1 }) => false
    183. */
    184. const hasOwnProperty = Object.prototype.hasOwnProperty
    185. if (isNil(value)) {
    186. return true
    187. }
    188. if (isArrayLike(value)) {
    189. return !value.length
    190. }
    191. const type = getType(value)
    192. if (type === 'Map' || type === 'Set') {
    193. return !value.size
    194. }
    195. if (isPrototype(value)) {
    196. return !Object.keys(value).length
    197. }
    198. for (const key in value) {
    199. if (hasOwnProperty.call(value, key)) {
    200. return false
    201. }
    202. }
    203. return true
    204. }
    205. export function isRegExp(value: unknown): value is RegExp {
    206. return isType(value, 'RegExp')
    207. }
    208. export function isDate(value: unknown): value is Date {
    209. return isType(value, 'Date')
    210. }
    211. export function isFormData(val: unknown) {
    212. return typeof FormData !== 'undefined' && val instanceof FormData
    213. }
    214. export function isPromise<T = any>(value: unknown): value is Promise<T> {
    215. return (
    216. isType(value, 'Promise') &&
    217. isObject(value) &&
    218. isFunction(value.then) &&
    219. isFunction(value.catch)
    220. )
    221. }
    222. export function isError(value: any): value is Error {
    223. return isType(value, 'Error')
    224. }
    225. /**
    226. * @Description: 两个数据是否相同
    227. * @param {any} value
    228. * @param {any} other
    229. */
    230. export function isEqual(value: any, other: any): boolean {
    231. if (value === other) {
    232. return true
    233. }
    234. if (!value || !other) {
    235. return false
    236. }
    237. if (isString(value) || isString(other)) {
    238. return false
    239. }
    240. if (isArrayLike(value) || isArrayLike(other)) {
    241. if (value.length !== other.length) {
    242. return false
    243. }
    244. let rst = true
    245. for (let i = 0; i < value.length; i++) {
    246. rst = isEqual(value[i], other[i])
    247. if (!rst) {
    248. break
    249. }
    250. }
    251. return rst
    252. }
    253. if (isObjectLike(value) || isObjectLike(other)) {
    254. const valueKeys = Object.keys(value)
    255. const otherKeys = Object.keys(other)
    256. if (valueKeys.length !== otherKeys.length) {
    257. return false
    258. }
    259. let rst = true
    260. for (let i = 0; i < valueKeys.length; i++) {
    261. rst = isEqual(value[valueKeys[i]], other[valueKeys[i]])
    262. if (!rst) {
    263. break
    264. }
    265. }
    266. return rst
    267. }
    268. return false
    269. }
    270. /**
    271. * @Description: 两个数据是否相同,不依赖其他函数,来自https://www.30secondsofcode.org/js/s/equals/
    272. * @param {any} value
    273. * @param {any} other
    274. */
    275. const equals = (a: any, b: any): boolean => {
    276. if (a === b) return true;
    277. if (a instanceof Date && b instanceof Date)
    278. return a.getTime() === b.getTime();
    279. if (!a || !b || (typeof a !== "object" && typeof b !== "object"))
    280. return a === b;
    281. if (a.prototype !== b.prototype) return false;
    282. const keys = Object.keys(a);
    283. if (keys.length !== Object.keys(b).length) return false;
    284. return keys.every((k) => equals(a[k], b[k]));
    285. };
    286. export function isWindow(value: any): value is Window {
    287. return typeof window !== 'undefined' && isType(value, 'Window')
    288. }
    289. // export function isElement(value: unknown): value is Element {
    290. // return isObject(value) && !!value.tagName
    291. // }
    292. /**
    293. * 判断是否HTML元素
    294. * @return {Boolean} 是否HTML元素
    295. */
    296. export function isElement(o: any): boolean {
    297. return o instanceof Element || o instanceof HTMLDocument
    298. }
    299. export const isServer = typeof window === 'undefined'
    300. export const isClient = !isServer
    301. export function isUrl(path: string): boolean {
    302. const reg =
    303. /(((^https?:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)$/
    304. return reg.test(path)
    305. }