
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
Pincet (Dutch for 'tweezers') is a plain simple - but still very powerful - array utility that is written in Typescript and, therefore, type safe.
npm i pincet
First, call Pincet in your code:
import * as pincet from 'pincet';
Pincet supports some plain simple methods, such as:
const arr = ['one', 'two', 'three'];
const first = pincet.findFirst<string>(arr);
console.log(first); // 'one'
However, you can use Pincet for nested arrays as well. For instance:
const arr = [[], [[]], ['one'], 'two', 'three'];
const first = pincet.findFirst<string>(arr);
console.log(first); // 'one'
You can also search for more values, if you prefer:
const arr = [[], ['one'], ['two']];
const first = pincet.findFirstNumber<string>(arr, 2);
console.log(first); // ['one', 'two']
Or revert it:
const arr = [[], ['one'], ['two']];
const last = pincet.findLastNumber<string>(arr, 2);
console.log(last); // ['two', 'one']
You can also find values with a predicate:
interface Person {
name: string,
age: number
}
const people: Person[][] = [
[
{
name: 'ChildA',
age: 10
},
{
name: 'ChildB',
age: 8
},
],
[
{
name: 'AdultA',
age: 40
},
{
name: 'AdultB',
age: 20
},
{
name: 'AdultC',
age: 30
},
{
name: 'AdultD',
age: 20
}
]
];
const predicate = (person: Person) => person.age === 30;
const result = pincet.findWithPredicate<Person>(people, predicate);
console.log(result); // [{ name: 'AdultC', age: 30 }]
If you like syntactic sugar, you can use pincet.findAny<Person>(people, predicate) as well.
You can also check if a (nested) array contains a value:
const arr = ['do', ['re'], 'mi'];
const result = pincet.contains<string>(arr, 're');
console.log(result); // true
Optionally, you can pass multiple values. If one of the values is in the array, the contains method returns true:
const arr = ['do', 're', 'mi', 'fa'];
const result = pincet.contains<string>(arr, 'so', 'la', 'ti', 'do');
console.log(result); // true
If you want to check if multiple values exist in an array, you can use pincet.containsAll():
const arr = ['aap', 'noot', 'mies', 'wim'];
const result = pincet.containsAll<string>(arr, 'mies', 'wim');
console.log(result); // true
Hence:
const arr = ['aap', 'noot', 'mies'];
const result = pincet.containsAll<string>(arr, 'mies', 'wim');
console.log(result); // false
You can also verify whether an array contains a partial value. This works for nested arrays as well. Example:
interface TestObject {
value: string;
isString: boolean;
}
const values: TestObject[] = [
{ value: 'aap', isString: true },
{ value: 'noot', isString: true }
];
const result = pincet.containsPartial<TestObject>(values, { value: 'aap' });
console.log(result); // true
Or:
const values: TestObject[] = [
{ value: 'aap', isString: true },
{ value: 'noot', isString: true }
];
const result = pincet.containsPartial<TestObject>(values, { value: 'mies' });
console.log(result); // false
const arr = [0, 1, 1, 2, 3, 3];
const result = pincet.unique<number>(arr);
console.log(result); // [0, 1, 2, 3]
You can specify a depth as well:
const arr1 = [0, 0, 1, [1], 2, 3, [3]];
const result1 = pincet.unique<number>(arr1);
console.log(result1); // [0, 1, [1], 2, 3, [3]]
const arr2 = [0, 0, 1, [1], 2, 3, [3]];
const result2 = pincet.unique<number>(arr2, 1);
console.log(result2); // [0, 1, 2, 3]
Interested in more results? Just split it:
interface Valid {
valid: true;
}
interface Invalid {
valid: false;
}
const arr: any[] = [
{
id: '1',
valid: true
},
{
id: '2',
valid: false
},
{
id: '3',
valid: true
},
];
const predicate = (value: any) => value.valid;
const [valid, invalid] = pincet.splitByPredicate<Valid, Invalid, any>(arr, predicate);
console.log(valid); // [{ id: '1', valid: true }, { id: '3', valid: true }];
console.log(invalid); // [{ id: '2', valid: false }];
You can also revert it:
const predicate = (value: any) => !value.valid;
const [invalid, valid] = pincet.splitByPredicate<Invalid, Valid, any>(arr, predicate);
Do you want to union some arrays? There are some Pincet functions for that!
const first: string[] = ['aap', 'noot'];
const second: string[] = ['mies'];
const result = union<string>(first, second);
console.log(result); // ['aap', 'noot', 'mies']
Or with predicate:
interface Person {
name: string;
age: number
}
const first: Person[] = [
{ name: 'Harry Potter', age: 18 }
];
const second: Person[] = [
{ name: 'Severus Snape', age: 38 },
{ name: 'Ronald Weasley', age: 18 }
];
const result = unionWith<Person>((p: Person) => p.age < 38, first, second);
console.log(result); // [{ name: 'Harry Potter', age: 18 }, { name: 'Ronald Weasley', age: 18 }]
You can also flatten multidimensional arrays as once. For this, just use flatUnion or flatUnionWith.
These methods do exactly the same as union and unionWith, but with the key difference that nested arrays are
flattened first. The depth of nested arrays is infinite.
Interested in equality? There is a method for that!
const arr1 = ['aap', ['noot', ['mies']]];
const arr2 = ['aap', ['noot', ['mies']]];
const result = pincet.isEqual(arr1, arr2);
console.log(result); // true
const arr1 = ['aap', 'noot', 'mies'];
const arr2 = ['aap', 'noot', 'mies'];
const arr3 = ['aap', 'noot', 'wim'];
const arr4 = ['aap', 'noot', 'mies'];
const result = pincet.isEqual(arr1, arr2, arr3, arr4);
console.log(result); // false
const arr = [0, 1, 2];
const fn = (v: number) => `${v + 1}`;
const result = pincet.map<number, string>(arr, fn);
console.log(result); // ['1', '2', '3']
By default, the map method does not flatten you array. If you want to flat map, you can!
const arr = [1, [2, [3]]];
const fn = (v: number) => v + 1;
const result = pincet.flatMap<number, number>(arr, fn);
console.log(result); // [2, 3, 4]
You can specify a depth, if you prefer. Here, we just pass a depth of 1:
const arr = [['aap', ['noot', ['mies']]]];
const fn = (v: string | string[]) => Array.isArray(v) ? v : 'wim';
const result = pincet.flatMap<string, string>(arr, fn, 1);
console.log(result); // ['wim', ['noot', ['mies']]]
If you want, Pincet supports mapping and converting values at once via the convertMap function:
interface Person {
name: string,
age: number
}
const arr: Person[][] = [
[
{ name: 'personA', age: 30 },
{ name: 'personB', age: 31 },
{ name: 'personC', age: 32 }
],
[
{ name: 'personD', age: 40 },
{ name: 'personE', age: 41 },
{ name: 'personF', age: 42 }
]
];
const result = pincet.convertMap<Person, 'age'>(arr, 'age');
console.log(result); // [[30, 31, 32], [40, 41, 42]]
Sometimes, you want to replace some values. Well, now you can with ease!
interface Person {
name: string;
gender: string;
}
const persons: Person[] = [
{ name: 'Bradley Edward Manning', gender: 'man' },
{ name: 'Nikkie de Jager', gender: 'man' }
];
const result = pincet.replaceAll<Person>(persons, { gender: 'woman' });
console.log(result); // [ { name: 'Bradley Edward Manning', gender: 'woman' }, { name: 'Nikkie de Jager', gender: 'woman' } ]
Not interested in replacing all values? Just pass a predicate:
interface Person {
name: string;
gender: string;
}
const persons: Person[] = [
{ name: 'Bradley Edward Manning', gender: 'man' },
{ name: 'Nikkie de Jager', gender: 'man' }
];
const predicate = (person: Person) => person.name === 'Nikkie de Jager';
const result = pincet.replaceAllWithPredicate<Person>(persons, { gender: 'woman' }, predicate);
console.log(result); // [ { name: 'Bradley Edward Manning', gender: 'man' }, { name: 'Nikkie de Jager', gender: 'woman' } ]
Pincet supports replacing one value (optionally with predicate), if needed. Technically this is not array related, but may still be handy!
const person: Person = { name: 'Bradley Edward Manning', gender: 'man' };
const result = pincet.replace<Person>(person, { gender: 'woman' });
console.log(result); // { name: 'Bradley Edward Manning', gender: 'woman' }
With Pincet, it is easy to remove a value from a (nested) array:
const arr = [0, 1, 2, 3];
const result = pincet.remove<number>(arr, 2);
console.log(result); // [0, 1, 3]
By default, Pincet respects nested arrays. Only when the removal operations leads to an empty array, the array will be filtered out:
const arr1 = [0, 1, [2], 3];
const result1 = pincet.remove<number>(arr1, 2);
console.log(result1); // [0, 1, 3]
const arr2 = [0, 1, [[2], 3]];
const result2 = pincet.remove<number>(arr2, 2);
console.log(result2); // [0, 1, [3]]
If you want, you can remove a value and flatten the array directly by using flatRemove:
const arr = [0, 1, [[2], 3]];
const result = pincet.flatRemove<number>(arr, 2);
console.log(result); // [0, 1, 3]
const arr = ['one', ['two', ['three', 'four'], 'five']];
const result = pincet.count(arr);
console.log(result); // 5
You can specify a depth:
const arr1 = ['one', ['two', ['three', 'four'], 'five']];
const result1 = pincet.count(arr1, 1);
console.log(result1); // 4
const arr2 = ['one', ['two', ['three', 'four'], 'five']];
const result2 = pincet.count(arr2, 0);
console.log(result2); // 2
Or just check for empty arrays:
const arr1: any[] = [[], []];
const result1 = pincet.isEmpty(arr1);
console.log(result1); // true
const arr2: any[] = [[], ['value']];
const result2 = pincet.isEmpty(arr2);
console.log(result2); // false
There is also a Count decorator. Please see 'supported decorators' in this readme.
Pincet provides a default sorting mechanism. By default, there are methods to sort on strings or numbers. For instance:
const arr = ['z', 'y', 'x'];
const result = pincet.sort<string>(arr, byStringAsc);
console.log(result); // ['x', 'y', 'z']
By default, Pincet does not flatten the array. If you want to, you can specify a depth:
const arr = [0, 1, [2]];
const result = pincet.sort<number>(arr, byNumberDesc, 1);
console.log(result); // [2, 1, 0]
At the moment, Pincet provided the following sorters by default:
You can, however, create your own sorter by extending the Sorter interface. The interface is just a type safe wrapper and holds a sorting function, that returns a number (just as the default comparator). Your implementation may look like this:
const myCustomSorter: Sorter<boolean> = { sort: (a, b) => a === b ? 1 : -1 };
You then may call it like:
const arr = [false, false, true, false, true];
const result = pincet.sort<boolean>(arr, myCustomSorter);
console.log(result); // [true, true, false, false, false]
Of course, Pincet supports nested arrays as well. Just pass a depth:
const arr = [false, [false], true, [false, [true]]];
const result = pincet.sort<boolean>(arr, myCustomSorter, 2);
console.log(result); // [true, true, false, false, false]
Wait, one more thing: flatten to the rescue! By default all arrays are flatten.
const arr = ['aap', ['noot'], [[['mies']]]];
const result = pincet.flatten<string>(arr);
console.log(result); // ['aap', 'noot', 'mies']
But you can specify a depth. For example:
const arr = ['aap', ['noot'], [[['mies']]]];
const result = pincet.flatten<string>(arr, 1);
console.log(result); // ['aap', 'noot', [['mies']]]
findFirst<T>(values: any[]): TfindFirstNumber<T>(values: any[], nValues: number): T[]findLast<T>(values: any[]): TfindLastNumber<T>(values: any[], nValues: number): T[]findWithPredicate<T>(values: T[], predicate: (value: T) => boolean): T[]findAny<T>(values: T[], guard: (value: T) => boolean): T[]contains<T>(values: unknown[], ...value: T): booleancontainsAll<T>(values: unknown[], ...value: T[]): booleancontainsPartial<T extends object>(values: object[], expectedPartial: Partial<T>): booleansplitByPredicate<T1, T2, S>(values: any[], predicate: (value: S) => boolean): [T1[], T2[]]union<T>(...list: T[][]): T[]unionWith<T>(predicate: (v: T) => boolean, ...list: T[][]): T[]flatUnion(...list: unknown[][]): unknown[]flatUnionWith(predicate: (v: any) => boolean, ...list: unknown[]): unknown[]flatten<T>(values: any[], depth: number = Infinity): T[]isEqual<T>(...arrays: T[][]): booleanmap<S, T>(values: S[], fn: (v: S) => T): T[]flatMap<S, T>(values: any[], fn: ((v: S | S[]) => T | any) | ((v: S) => T), depth: number = Infinity): T[]convertMap<S, K extends keyof S>(values: S[][], key: K): K[][]replace<T>(original: T, newValue: Partial<T>): TreplaceWithPredicate<T>(original: T, newValue: Partial<T>, predicate: (value: T) => boolean): TreplaceAll<T>(originalValues: T[], newValue: Partial<T>): T[]replaceAllWithPredicate<T>(originalValues: T[], newValue: Partial<T>, predicate: (value: T) => boolean): T[]count(values: any[], depth: number = Infinity): numberisEmpty(values: any[]): booleanunique<T>(values: any[], depth = 0): T[]sort<T>(values: any[], sorter: Sorter<T>, depth = 0): T[]remove<T>(values: any[], value: T): T[]flatRemove<T>(values: any[], value: T): T[]To enable the Pincet decorators, set experimentalDecorators in your tsconfig to true. This means that Typescript accepts custom decorators.
When you are only interested in a flat array, then you can use the Flatten decorator. It does exactly what is says:
class Host<T> {
@Flatten<T>() values: T[];
constructor(...values: any[]) {
this.values = values;
}
}
const host = new Host<string>(['aap', ['noot', ['mies']]]);
console.log(host.values); // ['aap', 'noot', 'mies']
Of course, with Pincet, you can almost always specify an optional depth:
class Host<T> {
@Flatten<T[]>(2) values: T[];
constructor(...values: any[]) {
this.values = values;
}
}
const host = new Host<string>(['aap', ['noot', ['mies']]]);
console.log(host.values); // ['aap', 'noot', ['mies']]
By default, the count decorator flattens the whole array. However, you can specify an optional depth.
class Host {
@Count() allValues: unknown[];
@Count(1) valuesWithDepthOne: unknown[];
constructor(...values: unknown[]) {
this.allValues = values;
this.valuesWithDepthOne = values;
}
}
const host = new Host('aap', 'noot', ['mies', ['wim', ['zus']]]);
console.log(host.allValues); // 5
console.log(host.valuesWithDepthOne); // 4
The empty decorator returns true when there are no values.
class Host {
@Empty() values: string[];
constructor(values: string[]) {
this.values = values;
}
}
const host1 = new Host([]);
console.log(host1.values); // true
const host2 = new Host(['aap']);
console.log(host2.values); // false
The not empty decorator returns true when there are values.
class Host {
@NotEmpty() values: string[];
constructor(values: string[]) {
this.values = values;
}
}
const host1 = new Host(['aap']);
console.log(host1.values); // true
const host2 = new Host([]);
console.log(host2.values); // false
npm installnpm run testJust check CHANGELOG.md to see the latest technical changes.
FAQs
For precise array operations only
The npm package pincet receives a total of 1 weekly downloads. As such, pincet popularity was classified as not popular.
We found that pincet demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.