Skip to content

Commit

Permalink
(feature) added from and of static methods
Browse files Browse the repository at this point in the history
  • Loading branch information
vigan-abd committed Apr 4, 2020
1 parent c140000 commit 1a1cf2e
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 1 deletion.
51 changes: 51 additions & 0 deletions src/array.js
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,57 @@ class ArrayT extends GenericType {
return value instanceof ArrayT
}

/**
* @param {string|Function} type
* @param {...any} values
* @returns {ArrayT}
*/
static of (type, ...values) {
return new ArrayT(type, ...values)
}

/**
* @param {string|Function} type
* @param {(value: any, index?: number, array?: ArrayT) => any} cb
* @param {*} thisArg
* @returns {ArrayT}
*/
static from (type, values, cb = null, thisArg = null) {
const res = new ArrayT(type)
if (values[Symbol.iterator]) {
const it = values[Symbol.iterator]()
let next = it.next()
let i = 0
while (!next.done) {
if (cb) {
const mappedItem = thisArg ? cb.call(thisArg, next.value, i, res) : cb(next.value, i, res)
res.push(mappedItem)
} else {
res.push(next.value)
}
next = it.next()
i++
}
} else if (typeof values === 'object' && values.length) { // { length: x }
const length = Number(values.length)
if (Number.isNaN(length)) return res
if (!Number.isFinite(length)) throw new RangeError('Invalid array length')

for (let i = 0; i < length; i++) {
if (cb) {
const mappedItem = thisArg ? cb.call(thisArg, undefined, i, res) : cb(undefined, i, res)
res.push(mappedItem)
} else {
res.push(undefined)
}
}
}

console.log(res)

return res
}

// #### Extended methods ####//
/**
* @returns {ArrayT}
Expand Down
67 changes: 66 additions & 1 deletion test/array.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,64 @@ module.exports = () => {
expect(arr.toArray()).to.be.eql([0, 1, 2, 3, 4, 5, 6, 7])
})

it('from - it should support iterables', () => {
expect(ArrayT.from('number', 1, 2, 3)).to.be.instanceOf(ArrayT)
expect(ArrayT.from('string', 'foo').toArray()).to.be.eql(['f', 'o', 'o'])
expect(ArrayT.from('number', [1, 2, 3], x => x + x).toArray()).to.be.eql([2, 4, 6])
expect(
ArrayT.from('string', new Set(['foo', 'bar', 'baz', 'foo'])).toArray()
).to.be.eql(['foo', 'bar', 'baz'])
expect(
ArrayT.from(Array, new Map([[1, 2], [2, 4], [4, 8]])).toArray()
).to.be.eql([[1, 2], [2, 4], [4, 8]])
expect(
ArrayT.from('string', new Map([['1', 'a'], ['2', 'b']]).values()).toArray()
).to.be.eql(['a', 'b'])
expect(
ArrayT.from('string', new Map([['1', 'a'], ['2', 'b']]).keys()).toArray()
).to.be.eql(['1', '2'])
})

it('from - it should support objects with length property', () => {
expect(
ArrayT.from('number', { length: 5 }, (_, i) => i).toArray()
).to.be.eql([0, 1, 2, 3, 4])
})

it('from - it should return empty array on unsupported object type', () => {
expect(ArrayT.from('string', { foo: 'bar' }).toArray()).to.be.eql([])
})

it('from - it should return empty array in case of negative length', () => {
expect(
ArrayT.from('number', { length: -3 }).toArray()
).to.be.eql([])
})

it('from - it should return empty array in case of NaN length', () => {
expect(
ArrayT.from('number', { length: 'a3' }).toArray()
).to.be.eql([])
})

it('from - it should throw an error in case of infinite length', () => {
expect(() => {
ArrayT.from('number', { length: Infinity }, (_, i) => i)
}).to.throw()
})

it('from - it should throw an error in case of invalid type', () => {
expect(() => {
ArrayT.from(typeof undefined, { length: 2 }).toArray()
}).to.be.throw()
expect(() => {
ArrayT.from('number', { length: 3 }, (v) => v)
}).to.throw()
expect(() => {
ArrayT.from('number', [1, 2, 3, '4'])
}).to.throw()
})

it('includes - it should return true if array includes element', () => {
expect(new ArrayT('number', 1, 2, 3).includes(2)).to.be.true()
expect(new ArrayT('string', 'a', 'b', 'c').includes('b')).to.be.true()
Expand Down Expand Up @@ -453,7 +511,7 @@ module.exports = () => {
})

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

it('of - it should generate an array from the values', () => {
expect(ArrayT.of('number', 1, 2, 3)).to.be.instanceOf(ArrayT)
expect(ArrayT.of('number', 1, 2, 3).toArray()).to.be.eql([1, 2, 3])
expect(ArrayT.of('number', 5).toArray()).to.be.eql([5])
expect(ArrayT.of('number').toArray()).to.be.eql([])
})

it('pop - it should behave like array', () => {
const numArray = new ArrayT('number', 2, 3)
expect(numArray.pop()).to.be.equal(3)
Expand Down

0 comments on commit 1a1cf2e

Please sign in to comment.