npm package: @jcstdio/jc-utils
Description: A tool set for JavaScript programming.
Author: Jack Lee
Latest version: 0.0.19

# JC Utils

A tool set for JavaScript programming.

```shell
npm i @jcstdio/jc-utils
# or
yarn add @jcstdio/jc-utils
# or
pnpm i @jcstdio/jc-utils
```

## judge tools （isXXX）

This part of the function is mainly used for all kinds of judgments, which are some of the most commonly used judgment tools. In fact, many open source projects have repeatedly implemented them, so it is necessary to encapsulate them.

```ts
// Such as:
import { isBoolean } from '@jcstdio/jc-utils'
```

### The first set of isXXX tools
This part is mostly type-related judgments.

| Tool name | describe |
|:-|:-| 
| isBoolean | Determine whether it is a Boolean value.
| isString | Determine whether it is a string.
| isNumber | Determine whether it is a number, excluding numbers represented by strings, etc.
| isNaNNumber | Determine whether it is NaN or not, so as to avoid the native isNaN function treating undefined equivalence as nan.
| isNotNaNNumber | Determine whether it is a non-NaN number.
| isInfinity | Determine whether it is infinite value `Infinity`.
| isNotInfinityNumber | A number that determines whether it is not Infinity.
| isNotNaNOrInfinityNumber | Determine whether it is a number that is not NaN and Infinity.
| isOddNumber | Determine whether a number is odd.
| isEvenNumber | Determine whether a number is an even number.
| isInt | Determine whether it is an integer.
| isObject | Determine whether it is an plain object.
| isSymbol | Determines whether it is a value of type symbol.
| isArray | Determine whether it is an array.
| isInt8Array | Determine whether it is an Int8Array instance.
| isUint8Array | Determine whether it is an instance of Uint8Array.
| isUint8ClampedArray | Determine whether it is an instance of Uint8ClampedArray.
| isInt16Array | Determine whether it is an instance of Int16Array.
| isUint16Array | Determine whether it is an instance of Uint16Array.
| isInt32Array | Determine whether it is an instance of Int32Array.
| isUint32Array | Determine whether it is an instance of Uint32Array.
| isBigInt64Array | Determine whether it is an instance of BigInt64Array.
| isBigUnit64Array | Determine whether it is an instance of BigUnit64Array.
| isFloat32Array | Determine whether it is an instance of Float32Array.
| isFloat64Array | Determine whether it is an instance of Float64Array.
| isArrayBuffer | Is it an ArrayBuffer instance?
| isDataView | Determine whether it is a DataView instance.
| isFunction | Determine whether it is a function.
| isMap | Determine whether it is a map (ES6 Map)
| isWeakMap | Determine whether it is a WeakMap instance.
| isSet | Determine whether it is a set (ES6 Set)
| isWeakSet | Determine whether it is a WeakSet instance.
| isWeakRef | Determine whether it is an instance of WeakRef.
| isRegExp | Determine whether it is regular or not.
| isDate | Determine whether it is a Date instance.
| isError | Determine whether it is an Error instance.
| isPrimitiver | Judge whether it is the original value.
| isPromise | Determine whether it is Promise.
| isDefined | Determine whether it is undefined.
| isUndefined | Determine whether it is undefined.
| isNull | Determine whether it is null.
| isNullAndUndefined | Returns true when isUndefined and isNull holds.
| isNullOrUndefined | Returns true when isNull or isUndefined.

### The second set of isXXX tools: string matching

This set of isXXX tools mainly detects whether it is a string in a certain format through regular expressions. Personally, I think these tools may be used more, and you can also quickly encapsulate them through the ready-made regular expression variables in *[12. Regularization and Regularization Tools ](#12)* (using the test method of regular objects).

| Tool name | describe |
|:-|:-| 
isChinese | Whether the match is a Chinese character.
isEnglish | Indicates whether it is an English letter.
isUrl | Indicates whether it is a URL address.
isPhone | A string indicating whether it is a mobile phone number.
isEmail | Indicates whether it is a mailbox address.
isIdCard | Indicates whether it is an ID number string.
isNumberStr | Represents a numeric string.
isDecimalStr | Represents a decimal string
isIntegerStr | Represents an integer string
isTime | Represents the time string format: hh:mm:ss
isPostalCode | String representing postal code
isHtmlTag | Represents an HTML tag string
isQQ | String representing QQ number
isWechat | Represents a micro signal string
isLicensePlate | String representing license plate number
isHexColor | A string represen a hexadecimal color value
isChineseName | String representing Chinese name
isBankCard | A string represen that bank card number.
isNumberAndLetter | A string represen a combination of numbers and letter.
isChineseEnglishNumberUnderline | Represents a string consisting of Chinese, English, numbers and underscores.
isChineseEnglishNumberSpace | Represents a string consisting of Chinese, English, numbers and spaces.
isChineseEnglishNumberDash | Represents a string consisting of Chinese, English, numbers and dash lines.
isChineseEnglishNumberSlash | Represents a string consisting of Chinese, English, numbers and slashes.
isChineseEnglishNumberColon | Represents a string consisting of Chinese, English, numbers and colons.
isChineseEnglishNumberQuestion | Represents a string consisting of Chinese, English, numbers and question marks.
isChineseEnglishNumberExclamation | Represents a string consisting of Chinese, English, numbers and exclamation points.


#@# The third set of isXXX tools: runtime


| Tool name | describe |
|:-|:-| 
isBrowser | Whether it is a browser.
isServer | Whether it is a server-side environment or not, compared with isNode, the tool will not check process.versions.node
isNode | Determine whether it is a NodeJS environment.
isElectron | Determine whether it is an election environment.
isBrowserAndNode | Meet the needs of both browsers and NodeJS operating environments, such as electron.
isNotBrowser | Not a browser environment
isNotServer | Not a server environment

## event tools


### EventEmitter tool

```js
import { EventEmitter } from '@jcstdio/jc-utils'
```

### StateManager tool

```js
import { StateManager } from '@jcstdio/jc-utils'

const stateManager = new StateManager<{
    value:number
}>({ value: 0, });

const sideEffec1 = (state: { value: any; }) => {
    console.log('我是 sideEffec1 ，状态被更新，当前状态值为：', state.value);
}

const sideEffec2 = () => {
  console.log('我是 sideEffec2 ，执行顺序为执行 “subscribe” 方法的顺序。')
}

// Set the callback after status update, which can be called by chain.
stateManager
  .subscribe(sideEffec1)
  .subscribe(sideEffec2)

// Update your status.
console.log('------- 第一次改变状态 -------');
stateManager.state = { value: 1 };

console.log('\n------- 第二次改变状态 -------');
stateManager
  .unsubscribe(sideEffec2)  // Cancel sideEffec2 subscribed when the status changes.
  .state = { value: 2 };    // Execute subscriptions that have not been cancelled.


```

**output**  **is:**

```
------- 第一次改变状态 -------
我是 sideEffec1 ，状态被更新，当前状态值为： 1
我是 sideEffec2 ，执行顺序为执行 “subscribe” 方法的顺序。

------- 第二次改变状态 -------
我是 sideEffec1 ，状态被更新，当前状态值为： 2
```

## ID Manager

### About ID Manage
In daily development, we often have the need to automatically assign a unique identifier (ID) to something. The ID manager is a unique identification value manager that **stores uniformly** and 
 **uses dispersedly**. With this manager, you can easily assign IDs to many different things-you only need to specify different things' names, so that one thing can be applied for non-repetitive identification strings.

### define things

The so-called **thing** is only any category that needs to use ID to identify its different individuals. For example, a student in a class can be regarded as a thing, and the student's student number can be managed as its ID. The purpose of defining things is to distinguish these things. For example, in a school, we not only need to distinguish students and assign them student numbers, but also need to use employee numbers to distinguish faculty and staff.

The `addThing` function is used to define things, and its type signature is as follows:

```ts
export declare function addThing(thingName: string, begin?: number): boolean;
```


- It accepts a string parameter (thingName) to identify the thing. For example:

```ts
import { addThing } from ''@jcstdio/jc-utils/id'

addThing('student'); // Adding student as a thing is equivalent to creating a new classification of student.
addThing('staff'); // Adding staff as a thing is equivalent to creating a new classification of staff.
```

- Another numerical parameter (`begin`) is used to specify the internally started count value, which will increase with the number of applied IDs, starting from 0 by default.

> Note: Things defined by using the `addThing` function in any module cannot be repeated.

### Application ID

Suppose a new student reports to the school. In order not to repeat the student number, we need to check the current student number position, then register a new student number for the new student and tell the student back. You can apply for a new ID by using the `getNewItemId` function. The type signature of this function is:

```ts
export declare function getNewItemId(thingName: string): string;
```

For example, apply for a new ID for students' classification as a new student number:

```ts
import { getNewItemId } from '@jcstdio/jc-utils/id'

const id = getNewItemId('student');
```

> By default, an ID string encoded by **Base64** is returned.

### Other APIs

You can try other APIs by referring to the following types of signatures:

```ts
declare type IDType = 'number' | 'simple' | 'baseb4';
/**Sets the type of return ID. */
export declare function setIdType(tp: IDType): void;
/**Gets the type of return ID (for viewing) */
export declare function getIdType(): IDType;
/**Create new things */
export declare function addThing(thingName: string, begin?: number): boolean;
/**Delete things */
export declare function dropThing(thingName: string): boolean;
/**Apply for a new ID for the specified thing. */
export declare function getNewItemId(thingName: string): string;
/**Get the current ID of something. */
export declare function getCurrentId(thingName: string): string;
/**Get the number of ids that something has given at present. */
export declare function countIds(thingName: string): number;
```



## exception tools

```ts
import { ValueError, InputTypeError } from '@jcstdio/jc-utils'

// ValueError is a function return a instance of Error
throw ValueError('Value Error.')
```


## noop/pass

```js
import { noop, pass } from '@jcstdio/jc-utils'

noop(); // do nothing
pass(); // do nothing
pass('hello','jack') // will print hello jack
```

## type conversion

```js
import { str, int } from '@jcstdio/jc-utils'

str(1);    // '1'
int('1');  // 1
```


## animate tools

### slide tool

This set of tools includes: slideUp、slideDown、verticalSlideToggle、slideLeft、slideRight、horizontalSlideToggle。

Their type signatures are:

 - Type signature of `slideUp`:
```ts
/**
 * Hide elements in a sliding way (imitating JQuery)
 *
 * @param element An Html element
 * @param duration Time to complete animation
 * @param targetHeight The height to be animated is 0 by default.
 */
declare function slideUp(element: HTMLElement, duration?: number, targetHeight?: number, removeStyleAfterFinished?: boolean): void;
/**
 * Show all hidden in a sliding way (imitating JQuery)
 *
 * @param element An Html element
 * @param duration Time to complete animation
 * @param removeStyleAfterFinished Whether to remove inline style tags after slideDown execution is completed. Since the slideToggle series functions are implemented by injecting inline style, removing the style attribute can restore the side effects caused by the SlideToggle series functions.
 */
declare function slideDown(element: HTMLElement, duration?: number, removeStyleAfterFinished?: boolean): void;
/**
 * Switch between slideUp and slideDown.
 *
 * That is, by checking the current height of the element and calling slideUp or slideDown accordingly.
 *
 * @param element An Html element
 * @param duration The time for an animation (slideUp or slideDown) is 200ms by default.
 * @returns
 * - true If the slideUp is finished (meaning that the previous height is greater than 0, the upward closing is performed)
 * - false If the slideDown is finished (which means opening down is performed)
 */
declare function verticalSlideToggle(element: HTMLElement, duration?: number): boolean;
/**
 * Switch between slideUp and slideDown.
 *
 * @deprecated This function has been renamed verticalSlideToggle and may be deleted at any time. Because there is also a new horizontalSlideToggle function to switch between slideLeft and slideRight.
 */
declare function slideToggle(element: HTMLElement, duration?: number): void;
/**
 * Hide elements to the left in a sliding manner.
 *
 *
 * @param element An Html element
 * @param duration Time to complete animation
 * @param targetWidth The width to be animated is 0 by default.
 * @param removeStyleAfterFinished Only used when slideLeft is used for restoring (generally speaking, during the Toggle period, one of slideLeft and slideRight is used for restoring), and the default value is false.
 */
declare function slideLeft(element: HTMLElement, duration?: number, targetWidth?: number, removeStyleAfterFinished?: boolean): void;
/**
 * Slide all hidden elements to the right.
 *
 * @param element An Html element
 * @param duration Time to complete animation
 * @param targetWidth Width when opened, the default is full width.
 * @param removeStyleAfterFinished Only used when slideRight is used for restore (generally speaking, during the Toggle period, one of slideLeft and slideRight is used for restore), and the default value is false.
 */
declare function slideRight(element: HTMLElement, duration?: number, targetWidth?: number | null, removeStyleAfterFinished?: boolean): void;
/**
 * Switch between slideLeft and slideRight. That is, by checking the current width of the element and calling slideLeft or slideRight accordingly.
 * @param element An Html element
 * @param duration The time for an animation (executing slideLeft or SlideEFT) is 200ms by default.
 * @param targetWidth The target width of slideRight when it is opened, and the default is full width.
 * @returns  Returns a boolean value that represents whether the element is closed or open after switching:
 * - true: Close, that is, slideLeft is executed.
 * - false: Open, that is, slideRight is executed.
 */
declare function horizontalSlideToggle(element: HTMLElement, duration?: number, targetWidth?: number | null, restoreBy?: 'Left' | 'Right'): boolean;
```


> **Note**: The slideToggle function of the old version (before v0.0.15) has been migrated to verticalSlideToggle and may be removed at any time.


For example:


```html
<template>
<ul @click="$event=>callBack()" ref="ulRef">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
</ul>
</template>

<script setup lang="ts">
import { getCurrentInstance, ref } from 'vue';
import type { ComponentInternalInstance } from 'vue;
import { verticalSlideToggle } from '@jcstdio/jc-utils'


const that = getCurrentInstance() as ComponentInternalInstance;

let callBack: () => void;

onMounted(()=>{
  const ulRef; = that.refs.ulRef as HTMLElement;
  callBack = () => {
    verticalSlideToggle(navRef);
  };
})
</script>


```


## logger tools

```ts
import { Logger } from '@jcstdio/jc-utils'

const logger = new Logger('')
logger.trace('trace')
logger.debug('debug')
logger.info('info')
logger.success('success')
logger.warn('warn')
logger.error('error')
logger.fatal('fatal')
logger.level1('level1')
logger.level2('level2')
logger.level3('level3')
logger.gradient('geadientText')
```

![logger.png](http://thispage.tech:9680/jclee1995/jc-utils-for-javascript/-/raw/master/logger.png)



##  math tools

### Arithmetic progression tool: arithmeticProgression

Used to construct a arithmetic progression array.

```ts
import { arithmeticProgression } from '@jcstdio/jc-utils'

arithmeticProgression(1,9,3);    // [ 1, 3, 5, 7, 9 ]
arithmeticProgression(9,1,3);    // [ 9, 7, 5, 3, 1 ]
arithmeticProgression(-9,-1,3);  // [ -9, -7, -5, -3, -1 ]
arithmeticProgression(-1,-9,3);  // [ -1, -3, -5, -7, -9 ]
arithmeticProgression(-1,-9,0);  // [ -1, -9 ]
arithmeticProgression(1,1,3);    // [ 1, 1, 1, 1, 1 ]
```

### Equispaced sequence generator: range
This tool is inspired by the range function provided in Python. In this module, range is a series of overloaded sequence generators that return an array.

The type signature of the range tool is as follows:

```ts
declare function range(x: number): number[];
declare function range(x: [number]): number[];
declare function range(x: [number, number]): number[];
declare function range(x: [number, number, number]): number[];
```

For example:

```ts
import { range } from '@jcstdio/jc-utils'

range([0, 3]);    // [0，1，2]
range(3);         // Equivalent to range([0, 3]), [0,1,2]
range([3]);       // Equivalent to range(3), [0,1,2]
range([4, 8, 1]); // [4, 5, 6, 7], where the last number indicates the interval.
range([4, 8, 2]); // [4, 6]
range([4, 8]);    // Equivalent to range([4, 8, 1]), [4, 5, 6, 7]
```

## vite tools


### getViteEnvs function

Filter all environment variables starting with VITE.

```ts
declare type filter = {
    test: string | RegExp;
    handle: (env: string) => any;
};

declare function getViteEnvs<T>(envConf: Recordable, filters?: filter[]): T;
```

## config tool 

### .ini config file

```ts
import { IniConfig } from '@jcstdio/jc-utils'
```

Type declaration of class `IniConfig` is:

```ts
declare class IniConfig {
    private _filePath;
    private _conf;
    constructor(_filePath?: string);
    get value(): Record<string, Record<string, any>>;
    load(obj: Record<string, Record<string, any>>): void;
    readSync<T>(filePath?: string): this;
    static format<U = Record<string, Record<string, any>>>(obj: U): string;
    private _farmat;
    writeSync(filePath?: string): void;
    addSection<V extends Record<string, any>>(section: string, records: V): this;
    addRecord<V>(section: string, key: string, value: V): this;
    getSection(section?: string): Record<string, any>;
    get(section?: string, key?: string): any;
    private __str__;
    print(): this;
}
```

### .env config file

```ts
import { getEnvs } from '@jcstdio/jc-utils'
```

Type declaration of function `getEnvs` is:

```ts
declare function getEnvs<T>(envFilePath: string, regExp?: RegExp, parse?: (right: string) => T): Record<string, T>;
```


## cache tools

### cookies tool

```ts
import { Cookies } from '@jcstdio/jc-utils'

let cookies = new Cookies();

```


### data structure tools

### LinkedList tool

```ts
import { List } from '@jcstdio/jc-utils'

```

### Series tool

A data structure inspired by pandas (a python package).

```ts
import { Series } from '@jcstdio/jc-utils'
```

examples:

```ts
import { Series } from '@jcstdio/jc-utils'

// Create a Series object.
const s = new Series([1, 2, 3, 4], { index: ['a', 'b', 'c', 'd'] });

// Use the map method to add 1 to each element in the Series.
const s1 = s.map((val: number) => val + 1);
s1.print()

// Use the dropNa method to delete NaN values in Series.
const s2 = new Series([1, 2, NaN, 4], { index: ['a', 'b', 'c', 'd'] });
s2.print()
const s3 = s2.dropNa();
s3.print()

// Use the fillNa method to replace the NaN value in Series with 0.
const s4 = new Series([1, 2, NaN, 4], { index: ['a', 'b', 'c', 'd'] });
s4.print()
const s5 = s4.fillNa({ value: 0 });
s5.print()

// Using isNa method to detect whether there is NaN value in Series.
const s6 = new Series([1, 2, NaN, 4], { index: ['a', 'b', 'c', 'd'] });
s6.print()
const hasNa = s6.isNa();

// Use the replace method to replace the specified value in Series with a new value.
const s7 = new Series([1, 2, 3, 4], { index: ['a', 'b', 'c', 'd'] });
s7.print()
const s8 = s7.replace(2, 5);
s8.print()

// Use the or method to return the logical or of two Series.
const s9 = new Series([true, false, true, false], { index: ['a', 'b', 'c', 'd'] });
s9.print()
const s10 = new Series([false, true, false, true], { index: ['a', 'b', 'c', 'd'] });
s10.print()
const s11 = s9.or(s10);
s11.print()

// Use the and method to return the logical sum of two Series.
const s12 = new Series([true, false, true, false], { index: ['a', 'b', 'c', 'd'] });
s12.print()
const s13 = new Series([false, true, false, true], { index: ['a', 'b', 'c', 'd'] });
s13.print()
const s14 = s12.and(s13);
s14.print()

// Use argSort method to return the index sorted by Series.
const s15 = new Series([3, 1, 4, 2], { index: ['a', 'b', 'c', 'd'] });
s15.print()
const sortedIndex = s15.argSort({ ascending: true });
console.log('sortedIndex =',sortedIndex);


// Use the argMin method to return the index of the smallest value in the Series.
const s16 = new Series([3, 1, 4, 2], { index: ['a', 'b', 'c', 'd'] });
s16.print()
const minIndex = s16.argMin();
console.log('minIndex =',minIndex)

// Use the argMax method to return the index of the largest value in the Series.
const s17 = new Series([3, 1, 4, 2], { index: ['a', 'b', 'c', 'd'] });
s17.print()
const maxIndex = s17.argMax({ ascending: true });
console.log('maxIndex =',maxIndex)

// Use the sortValues method to return the new Series sorted by Series.
const s18 = new Series([3, 1, 4, 2], { index: ['a', 'b', 'c', 'd'] });
s18.print()
const sortedSeries = s18.sortValues({ ascending: true });
s18.print('sortedSeries =',sortedSeries)

// Print Series using the print method.
const s19 = new Series([1, 2, 3, 4], { index: ['a', 'b', 'c', 'd'] });
s19.print()
```

## copy tools

Provides tools for shallow and deep copying of JavaScript objects.

```
import { copy } from '@jcstdio/jc-utils'

// Shallow copy
const obj1 = {a: 1, b: {c: 2}};
const shallowCopyObj1 = copy.shallowCopy(obj1);
console.log(shallowCopyObj1); // {a: 1, b: {c: 2}}
console.log(shallowCopyObj1.b === obj1.b); // true

// DeepCopy realized by deepcopy method (recursive replication nested object implementation)
const obj2 = {a: 1, b: {c: 2}};
const deepCopyObj2 = copy.deepCopy(obj2);
console.log(deepCopyObj2); // {a: 1, b: {c: 2}}
console.log(deepCopyObj2.b === obj2.b); // false

// Deep copy realized by serializeCopy method (realized by JSON serialization and deserialization)
const obj3 = {a: 1, b: {c: 2}};
const serializeCopyObj3 = copy.serializeCopy(obj3);
console.log(serializeCopyObj3); // {a: 1, b: {c: 2}}
console.log(serializeCopyObj3.b === obj3.b); // false

```

## Codec tool

### String encoding and decoding tool based on Base64

This section provides two tools, `strEncodeBase64` and `strBase64Decode`, which are used for Base64 encoding and restoring of strings respectively. Their type signatures are as follows:

> since v0.0.17

- strEncodeBase64
```ts
/**
 * Base64 encode a string.
 * @param str A string
 * @returns Base64 encoded string.
 */
export declare function strEncodeBase64(str: string): string;
```

- strBase64Decode
```ts
/**
 * Restores a string encoded by Base64 to the original string.
 * @param str A string
 * @returns Base64 Decoded string
 */
export declare function strBase64Decode(str: string): string;
```


## Proxy and Reactive Tools

### Proxy tools

#### Agent creator of Array

The `createArrayProxy` function is used to create the proxy of Array, and its function is more powerful than the original Array. For example:

1. The array after proxy can be indexed negatively.
2. Delete the element at the specified index without leaving any space.
-You can use either the delete keyword or the extended drop method. However, it should be pointed out that this drop method exists only on proxy objects.
3. Automatically assign an event to the agent's object every time the function is called, and you can specify the side effects of the event to realize responsive data.

The type signature of the **createArrayProxy** tool is as follows:

```ts
declare type printType = 'log' | 'json';
declare type ArrayProxy<T> = Array<T> & {
    drop: (index: number) => void;
    print: (type?: printType) => any;
};
/**
 * Create a proxy for Array
 * - Negative numbers can be indexed.
 * - Delete the element at the specified index without leaving a space.
 * - An event is automatically assigned to the agent's object every time a function is called, and the side effects of the event can be specified to realize responsive data.
 * @param target The target object of the proxy
 * @returns Object after proxy
 */
declare function createArrayProxy<T>(target: Array<T>, sideEffect?: (...params: any[]) => any): ArrayProxy<T>;
```

For example:

```ts
import { createArrayProxy } from './dist';

let arProxy1 = createArrayProxy([0,1,2,'3'])
console.log('arProxy1 =',arProxy1);
console.log('---------- 测试索引 ----------');
console.log('ar[1] =',arProxy1[1]);
console.log('ar[0] =',arProxy1[0]);
console.log('ar[0] =',arProxy1[-1]);
console.log('ar[-1] =',arProxy1[-1]);
console.log('ar[-2] =',arProxy1[-2]);
console.log('ar[-3] =',arProxy1[-3]);
console.log('---------- 测试length属性 ----------');
console.log('.length =',arProxy1.length);
console.log('---------- 测试 pop、push 等方法 ----------');
arProxy1.pop()
console.log('ar.pop() =',arProxy1);
arProxy1.push(3)
console.log('ar.push(3) =',arProxy1);

arProxy1.forEach((item)=>{
    console.log('item =',item);
})

console.log('---------- 测试 delete ----------');
console.log('delete arProxy1[1]:');
delete arProxy1[1]
console.log(arProxy1);
console.log('---------- 测试扩展的方法 ----------');
arProxy1.drop(2);
console.log('ar.drop(2) =',arProxy1);
console.log('print方法输出 arProxy2:');

const arProxy2 = createArrayProxy([
    0,
    [1,2,3,{}],
    {a:1,b:[1,2,3]},
    3
])

arProxy2.print()

console.log('---------- 测试 delete ----------');

console.log('delete arProxy2[1]:');
delete arProxy2[1]
console.log(arProxy2);
```

`OutPuts:`

```console
arProxy1 = [ 0, 1, 2, '3' ]
---------- 测试索引 ----------
ar[1] = 1
ar[0] = 0
ar[0] = 3
ar[-1] = 3
ar[-2] = 2
ar[-3] = 1
---------- 测试length属性 ----------
.length = 4
---------- 测试 pop、push 等方法 ----------
ar.pop() = [ 0, 1, 2 ]
ar.push(3) = [ 0, 1, 2, 3 ]
---------- 测试迭代器 ----------
item = 0
item = 1
item = 2
item = 3
---------- 测试 delete ----------
delete arProxy1[1]:
[ 0, 2, 3 ]
---------- 测试扩展的方法 ----------
ar.drop(2) = [ 0, 2 ]
print方法输出 arProxy2:
[ 0, [ 1, 2, 3, {} ], { a: 1, b: [ 1, 2, 3 ] }, 3 ]
---------- 测试 delete ----------
delete arProxy2[1]:
[ 0, { a: 1, b: [ 1, 2, 3 ] }, 3 ]
```


#### Agent creator of Set 

> Not yet completed

#### Agent creator of Map 

> Not yet completed

## Type Tools


A set of tools for TypeScript Type.Type signatures of all types of tools are as follows:

export from: `@jcstdio/jc-utils/ts`, you must to import from '@jcstdio/jc-utils/ts', for example:

```ts
import type { RequiredKeys, Recordable } from '@jcstdio/jc-utils/ts'
```

Include that following type of tools:

| Type tool | describe
|:-|:-|
|RequiredKeys\<T> | 构造一个由所需的 T 的键组成的类型。
|Mutable\<T>| 构造 T 的所有属性都设置为可变的类型。
|RequiredExcept\<T, K>| 构造T的所有属性都设置为 required 的类型，k中指定的属性除外。
|ReadonlyExcept\<T, K> | 构造 T 的所有属性都设置为 readonly 的类型，K中指定的属性除外。
|MutableExcept\<T, K> | 构造一个类型，其中 T 的所有属性都设置为可变，K 中指定的属性除外。
|PickByValue\<T, V> | 通过选取值为 V 类型的 T 的属性来构造类型。
|OmitByValue\<T, V> | 通过省略 T 的值为 V 类型的属性来构造类型。
|Intersection\<T, U> | 构造一个由 T 和 U 中的所有属性组成的类型。
|Diff\<T, U> | 构造一个类型，它包含T中但U中没有的所有属性。
|Subtract\<T, U>| 构造一个类型，由T中但不在 T 和 U 的交集中的所有属性组成。
|Overwrite\<T, U> | 构造一个由 T 和 U 的所有属性组成的类型，其中 U 的属性覆盖 T 的同名属性。
|UnionToIntersection\<T> | 构造一个类型，该类型由 T 中所有类型的交集中的所有属性组成。
|FunctionKeys<T>| 造一个由T的键组成的类型，这些键是函数。
|NonFunctionKeys\<T> | 构造一个由 T 的非函数键组成的类型。
|PromiseType\<T> | 构造一个由 Promise-like 类型 T 的已解析类型组成的类型。
|DeepReadonly\<T> | 构造一个 T 的所有属性都递归设置为只读的类型。
|DeepPartial\<T> | 递归地构造 T 的所有属性都设置为可选的类型。
|ValueOf\<T> | 构造由 T 中所有值的并集组成的类型。
|OptionalKeys\<T>| 构造一个由 T 的可选键组成的类型。
|ReadonlyKeys\<T> | 构造一个由 T 的只读键组成的类型。
|WritableKeys<T> | 构造一个由 T 的可写键组成的类型。
|DeepRequired\<T> | 递归地构造 T 的所有属性都设置为 required 的类型。
|DeepWritable\<T>| 构造 T 的所有属性都设置为可递归写的类型。
|DeepNonNullable<T> | 构造一个类型，其中 T 的所有属性都递归地设置为 non-nullable。
|Immutable\<T> | 构造 T 的所有属性都设置为不可变的类型。
|Unionize<T> | 构造 T 中所有可能的性质排列的联合类型。
|Exclusive\<T, U> | 通过从 T 中挑选所有不属于 T 或 U 的属性来构造类型。
|Intersect\<T, U> | 通过从 T 中选取所有也在 U 中的属性来构造类型。
|Assign\<T, U>| 通过从 T 和 U 中选取所有属性并将它们合并在一起来构造一个类型。
|DeepMutable\<T>| 构造一个 T 的所有属性都设置为可变递归的类型。
|Promisable\<T> | 构造一个 T 的所有属性都设置为 Promisable 的类型。
|Awaited\<T> | 构造一个类型，将 T 的所有属性设置为 awaited 类型。
|Brand\<T, U> | 通过用附加的 U 类型包装 T 来构造一个标称类型。
|NonUndefined\<T> | 通过从 T 中选取所有未定义的属性来构造类型。
| Recordable\<T = any> | 构造一个类型，该类型是一个拥有字符串类型键和任意类型值的记录，类似于JavaScript中的对象。|
| ReadonlyRecordable\<T = any> | 构造一个类型，该类型是一个拥有字符串类型键和只读 T 类型值的记录，类似于JavaScript中的对象。 |
| Indexable\<T = any> | 构造一个类型，该类型是一个拥有字符串类型键和任意类型值的记录，类似于JavaScript中的对象。 |
| TimeoutHandle | setTimeout 函数返回的计时器 ID 类型。 |
| IntervalHandle | setInterval 函数返回的计时器 ID 类型。 |
| ChangeEvent | 表示一个输入元素的状态变化事件。继承自 Event。 |