Source: Queue.js

const [Queue, TypedQueue] = ( function(){
	/**
   * A class that represents a queue. When an item is added, it is added to the top. When an item is removed, it is removed from the bottom.
   * @class
   */
	class Queue {
	  /**
	   * @constructs Queue
	   */
		constructor() {
			this.__elems__ = [];
		}
		/**
		 * The number of items in the queue.
		 */
		get items() {
			return this.__elems__.length;
		}
		/**
		 * Add an item to the queue
		 * @param {...*} items The items to add.
		 * @returns {undefined}
		 */
		add( ...items ) {
			this.__elems__.push( ...items );
		}
		/**
		 * Get the bottom item from the queue.
		 * @returns {*} The item.
		 */
		remove() {
			return this.__elems__.shift();
		}
		*[Symbol.iterator]() {
			while( this.items ) {
    	  yield this.remove();
    	}
		}
	}
	class TypedQueue extends Queue {
		constructor( ...types ) {
    	if( types.all( type=>typeof type === 'function' && type.prototype ) ) {
    	  super();
    	  this.__types__ = types;
    	} else {
    	  throw TypeError( 'TypedStack expects an array of types.' );
    	}
		}
		add( ...items ) {
			items.forEach( ( item, _ ) => {
				if( this.__types__.some( type=>item instanceof type ) ) {
					super.add( item );
				} else {
					throw TypeError( `Invalid item: ${item}` );
				}
			} );
		}
	}
	return [Queue, TypedQueue];
} )();