types/make.js
function generatePrefixed(prefix) {
	let output = '';
	let children = '';

	for (const part of allParts) {
		const parts = prefix.concat([part]);

		if (prefix.indexOf(part) !== -1 || !verify(parts, true)) {
			// Function already in prefix or not allowed here
			continue;
		}

		// If `parts` is not sorted, we alias it to the sorted chain
		if (!isArraySorted(parts)) {
			if (exists(parts)) {
				parts.sort();

				let chain;
				if (hasChildren(parts)) {
					chain = parts.join('_') + '<T>';
				} else {
					// This is a single function, not a namespace, so there's no type associated
					// and we need to dereference it as a property type
					const last = parts.pop();
					const joined = parts.join('_');
					chain = `${joined}<T>['${last}']`;
				}

				output += `\t${part}: Register_${chain};\n`;
			}

			continue;
		}

		// Check that `part` is a valid function name.
		// `always` is a valid prefix, for instance of `always.after`,
		// but not a valid function name.
		if (verify(parts, false)) {
			if (arrayHas(parts)('todo')) {
				// 'todo' functions don't have a function argument, just a string
				output += `\t${part}: (name: string) => void;\n`;
			} else {
				if (arrayHas(parts)('cb')) {
					output += `\t${part}: CallbackRegisterBase<T>`;
				} else {
					output += `\t${part}: RegisterBase<T>`;
				}

				if (hasChildren(parts)) {
					// This chain can be continued, make the property an intersection type with the chain continuation
					const joined = parts.join('_');
					output += ` & Register_${joined}<T>`;
				}

				output += ';\n';
			}
		}

		children += generatePrefixed(parts);
	}

	if (output === '') {
		return children;
	}

	const typeBody = `{\n${output}}\n${children}`;

	if (prefix.length === 0) {
		// No prefix, so this is the type for the default export
		return `export interface Register<T> extends RegisterBase<T> ${typeBody}`;
	}
	const namespace = ['Register'].concat(prefix).join('_');
	return `interface ${namespace}<T> ${typeBody}`;
}
function generatePrefixed(prefix) {
	let output = '';
	let children = '';

	for (const part of allParts) {
		const parts = prefix.concat([part]);

		if (prefix.indexOf(part) !== -1 || !verify(parts, true)) {
			// Function already in prefix or not allowed here
			continue;
		}

		// If `parts` is not sorted, we alias it to the sorted chain
		if (!isArraySorted(parts)) {
			if (exists(parts)) {
				parts.sort();

				let chain;
				if (hasChildren(parts)) {
					chain = parts.join('_') + '<T>';
				} else {
					// This is a single function, not a namespace, so there's no type associated
					// and we need to dereference it as a property type
					const last = parts.pop();
					const joined = parts.join('_');
					chain = `${joined}<T>['${last}']`;
				}

				output += `\t${part}: Register_${chain};\n`;
			}

			continue;
		}

		// Check that `part` is a valid function name.
		// `always` is a valid prefix, for instance of `always.after`,
		// but not a valid function name.
		if (verify(parts, false)) {
			if (arrayHas(parts)('todo')) {
				// 'todo' functions don't have a function argument, just a string
				output += `\t${part}: (name: string) => void;\n`;
			} else {
				if (arrayHas(parts)('cb')) {
					output += `\t${part}: CallbackRegisterBase<T>`;
				} else {
					output += `\t${part}: RegisterBase<T>`;
				}

				if (hasChildren(parts)) {
					// This chain can be continued, make the property an intersection type with the chain continuation
					const joined = parts.join('_');
					output += ` & Register_${joined}<T>`;
				}

				output += ';\n';
			}
		}

		children += generatePrefixed(parts);
	}

	if (output === '') {
		return children;
	}

	const typeBody = `{\n${output}}\n${children}`;

	if (prefix.length === 0) {
		// No prefix, so this is the type for the default export
		return `export interface Register<T> extends RegisterBase<T> ${typeBody}`;
	}
	const namespace = ['Register'].concat(prefix).join('_');
	return `interface ${namespace}<T> ${typeBody}`;
}
function generatePrefixed ( prefix ) { let output = '' ; let children = '' ; for ( const part of allParts ) { const parts = prefix . concat ( [ part ] ) ; if ( prefix . indexOf ( part ) !== - 1 || ! verify ( parts , true ) ) { // Function already in prefix or not allowed here continue ; } // If `parts` is not sorted, we alias it to the sorted chain if ( ! isArraySorted ( parts ) ) { if ( exists ( parts ) ) { parts . sort ( ) ; let chain ; if ( hasChildren ( parts ) ) { chain = parts . join ( '_' ) + '<T>' ; } else { // This is a single function, not a namespace, so there's no type associated // and we need to dereference it as a property type const last = parts . pop ( ) ; const joined = parts . join ( '_' ) ; chain = ` ${ joined } ${ last } ` ; } output += ` \t ${ part } ${ chain } \n ` ; } continue ; } // Check that `part` is a valid function name. // `always` is a valid prefix, for instance of `always.after`, // but not a valid function name. if ( verify ( parts , false ) ) { if ( arrayHas ( parts ) ( 'todo' ) ) { // 'todo' functions don't have a function argument, just a string output += ` \t ${ part } \n ` ; } else { if ( arrayHas ( parts ) ( 'cb' ) ) { output += ` \t ${ part } ` ; } else { output += ` \t ${ part } ` ; } if ( hasChildren ( parts ) ) { // This chain can be continued, make the property an intersection type with the chain continuation const joined = parts . join ( '_' ) ; output += ` ${ joined } ` ; } output += ';\n' ; } } children += generatePrefixed ( parts ) ; } if ( output === '' ) { return children ; } const typeBody = ` \n ${ output } \n ${ children } ` ; if ( prefix . length === 0 ) { // No prefix, so this is the type for the default export return ` ${ typeBody } ` ; } const namespace = [ 'Register' ] . concat ( prefix ) . join ( '_' ) ; return ` ${ namespace } ${ typeBody } ` ; }
Generates type definitions, for the specified prefix The prefix is an array of function names
Generates type definitions for the specified prefix The prefix is an array of function names