Skip to content

Commit 1a1cf2e

Browse files
committed
(feature) added from and of static methods
1 parent c140000 commit 1a1cf2e

File tree

2 files changed

+117
-1
lines changed

2 files changed

+117
-1
lines changed

src/array.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,57 @@ class ArrayT extends GenericType {
582582
return value instanceof ArrayT
583583
}
584584

585+
/**
586+
* @param {string|Function} type
587+
* @param {...any} values
588+
* @returns {ArrayT}
589+
*/
590+
static of (type, ...values) {
591+
return new ArrayT(type, ...values)
592+
}
593+
594+
/**
595+
* @param {string|Function} type
596+
* @param {(value: any, index?: number, array?: ArrayT) => any} cb
597+
* @param {*} thisArg
598+
* @returns {ArrayT}
599+
*/
600+
static from (type, values, cb = null, thisArg = null) {
601+
const res = new ArrayT(type)
602+
if (values[Symbol.iterator]) {
603+
const it = values[Symbol.iterator]()
604+
let next = it.next()
605+
let i = 0
606+
while (!next.done) {
607+
if (cb) {
608+
const mappedItem = thisArg ? cb.call(thisArg, next.value, i, res) : cb(next.value, i, res)
609+
res.push(mappedItem)
610+
} else {
611+
res.push(next.value)
612+
}
613+
next = it.next()
614+
i++
615+
}
616+
} else if (typeof values === 'object' && values.length) { // { length: x }
617+
const length = Number(values.length)
618+
if (Number.isNaN(length)) return res
619+
if (!Number.isFinite(length)) throw new RangeError('Invalid array length')
620+
621+
for (let i = 0; i < length; i++) {
622+
if (cb) {
623+
const mappedItem = thisArg ? cb.call(thisArg, undefined, i, res) : cb(undefined, i, res)
624+
res.push(mappedItem)
625+
} else {
626+
res.push(undefined)
627+
}
628+
}
629+
}
630+
631+
console.log(res)
632+
633+
return res
634+
}
635+
585636
// #### Extended methods ####//
586637
/**
587638
* @returns {ArrayT}

test/array.test.js

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,64 @@ module.exports = () => {
380380
expect(arr.toArray()).to.be.eql([0, 1, 2, 3, 4, 5, 6, 7])
381381
})
382382

383+
it('from - it should support iterables', () => {
384+
expect(ArrayT.from('number', 1, 2, 3)).to.be.instanceOf(ArrayT)
385+
expect(ArrayT.from('string', 'foo').toArray()).to.be.eql(['f', 'o', 'o'])
386+
expect(ArrayT.from('number', [1, 2, 3], x => x + x).toArray()).to.be.eql([2, 4, 6])
387+
expect(
388+
ArrayT.from('string', new Set(['foo', 'bar', 'baz', 'foo'])).toArray()
389+
).to.be.eql(['foo', 'bar', 'baz'])
390+
expect(
391+
ArrayT.from(Array, new Map([[1, 2], [2, 4], [4, 8]])).toArray()
392+
).to.be.eql([[1, 2], [2, 4], [4, 8]])
393+
expect(
394+
ArrayT.from('string', new Map([['1', 'a'], ['2', 'b']]).values()).toArray()
395+
).to.be.eql(['a', 'b'])
396+
expect(
397+
ArrayT.from('string', new Map([['1', 'a'], ['2', 'b']]).keys()).toArray()
398+
).to.be.eql(['1', '2'])
399+
})
400+
401+
it('from - it should support objects with length property', () => {
402+
expect(
403+
ArrayT.from('number', { length: 5 }, (_, i) => i).toArray()
404+
).to.be.eql([0, 1, 2, 3, 4])
405+
})
406+
407+
it('from - it should return empty array on unsupported object type', () => {
408+
expect(ArrayT.from('string', { foo: 'bar' }).toArray()).to.be.eql([])
409+
})
410+
411+
it('from - it should return empty array in case of negative length', () => {
412+
expect(
413+
ArrayT.from('number', { length: -3 }).toArray()
414+
).to.be.eql([])
415+
})
416+
417+
it('from - it should return empty array in case of NaN length', () => {
418+
expect(
419+
ArrayT.from('number', { length: 'a3' }).toArray()
420+
).to.be.eql([])
421+
})
422+
423+
it('from - it should throw an error in case of infinite length', () => {
424+
expect(() => {
425+
ArrayT.from('number', { length: Infinity }, (_, i) => i)
426+
}).to.throw()
427+
})
428+
429+
it('from - it should throw an error in case of invalid type', () => {
430+
expect(() => {
431+
ArrayT.from(typeof undefined, { length: 2 }).toArray()
432+
}).to.be.throw()
433+
expect(() => {
434+
ArrayT.from('number', { length: 3 }, (v) => v)
435+
}).to.throw()
436+
expect(() => {
437+
ArrayT.from('number', [1, 2, 3, '4'])
438+
}).to.throw()
439+
})
440+
383441
it('includes - it should return true if array includes element', () => {
384442
expect(new ArrayT('number', 1, 2, 3).includes(2)).to.be.true()
385443
expect(new ArrayT('string', 'a', 'b', 'c').includes('b')).to.be.true()
@@ -453,7 +511,7 @@ module.exports = () => {
453511
})
454512

455513
it('isArrayT - it should return true if value is instance of ArrayT', () => {
456-
class ArrayB extends ArrayT {}
514+
class ArrayB extends ArrayT { }
457515
expect(ArrayT.isArrayT(new ArrayT('number', 1, 2))).to.be.true()
458516
expect(ArrayT.isArrayT(new ArrayB('number'))).to.be.true()
459517
})
@@ -604,6 +662,13 @@ module.exports = () => {
604662
expect(arr.toArray()).to.be.eql([0, 1, 2, 3, 4, 5, 6, 7])
605663
})
606664

665+
it('of - it should generate an array from the values', () => {
666+
expect(ArrayT.of('number', 1, 2, 3)).to.be.instanceOf(ArrayT)
667+
expect(ArrayT.of('number', 1, 2, 3).toArray()).to.be.eql([1, 2, 3])
668+
expect(ArrayT.of('number', 5).toArray()).to.be.eql([5])
669+
expect(ArrayT.of('number').toArray()).to.be.eql([])
670+
})
671+
607672
it('pop - it should behave like array', () => {
608673
const numArray = new ArrayT('number', 2, 3)
609674
expect(numArray.pop()).to.be.equal(3)

0 commit comments

Comments
 (0)