_print(type, object, baseContext) {
		/** @type {StatsPrinterContext} */
		const context = {
			...baseContext,
			type,
			[type]: object
		};

		/** @type {string | undefined} */
		let printResult = this._forEachLevel(this.hooks.print, type, hook =>
			hook.call(object, context)
		);
		if (printResult === undefined) {
			if (Array.isArray(object)) {
				const sortedItems = object.slice();
				this._forEachLevel(this.hooks.sortItems, type, h =>
					h.call(
						sortedItems,
						/** @type {StatsPrinterContextWithExtra} */
						(context)
					)
				);
				const printedItems = sortedItems.map((item, i) => {
					const itemContext =
						/** @type {StatsPrinterContextWithExtra} */
						({
							...context,
							_index: i
						});
					const itemName = this._forEachLevel(
						this.hooks.getItemName,
						`${type}[]`,
						h => h.call(item, itemContext)
					);
					if (itemName) itemContext[itemName] = item;
					return this.print(
						itemName ? `${type}[].${itemName}` : `${type}[]`,
						item,
						itemContext
					);
				});
				printResult = this._forEachLevel(this.hooks.printItems, type, h =>
					h.call(
						/** @type {string[]} */ (printedItems),
						/** @type {StatsPrinterContextWithExtra} */
						(context)
					)
				);
				if (printResult === undefined) {
					const result = printedItems.filter(Boolean);
					if (result.length > 0) printResult = result.join("\n");
				}
			} else if (object !== null && typeof object === "object") {
				const elements = Object.keys(object).filter(
					key => object[key] !== undefined
				);
				this._forEachLevel(this.hooks.sortElements, type, h =>
					h.call(
						elements,
						/** @type {StatsPrinterContextWithExtra} */
						(context)
					)
				);
				const printedElements = elements.map(element => {
					const content = this.print(`${type}.${element}`, object[element], {
						...context,
						_parent: object,
						_element: element,
						[element]: object[element]
					});
					return { element, content };
				});
				printResult = this._forEachLevel(this.hooks.printElements, type, h =>
					h.call(
						printedElements,
						/** @type {StatsPrinterContextWithExtra} */
						(context)
					)
				);
				if (printResult === undefined) {
					const result = printedElements.map(e => e.content).filter(Boolean);
					if (result.length > 0) printResult = result.join("\n");
				}
			}
		}

		return this._forEachLevelWaterfall(
			this.hooks.result,
			type,
			/** @type {string} */
			(printResult),
			(h, r) => h.call(r, /** @type {StatsPrinterContextWithExtra} */ (context))
		);
	}
@private
@param {string} type type
@param {PrintObject} object object
@param {StatsPrinterContext=} baseContext context
@returns {string | undefined} printed result