docs: function compileDeserializer( attributes ) {
  	if ( !attributes || typeof attributes !== "object" || Array.isArray( attributes ) ) {
  		throw new TypeError( "definition of attributes must be object" );
  	}
  
  	const attributeNames = Object.keys( attributes );
  	const numAttributes = attributeNames.length;
  	const deserialization = new Array( 2 * numAttributes );
  
  	let write = 0;
  	for ( let ai = 0; ai < numAttributes; ai++ ) {
  		const attributeName = attributeNames[ai];
  		const attribute = attributes[attributeName];
  
  		const handler = Types.selectByName( attribute.type );
  		let sourceName;
  
  		// append deserialize() method of current attribute's type handler
  		{
  			const { args, body } = extractBody( handler.deserialize );
  			if ( args.length < 1 ) {
  				throw new TypeError( `deserialize() of ModelType for handling ${attribute.type} values must accept one argument` );
  			}
  
  			if ( body.replace( ptnTrailingReturn, "" ).trim().length ) {
  				sourceName = "$$d";
  				deserialization[write++] = `
  {
  	let ${args[0]} = $$s["${attributeName}"];
  
  	{
  		${body.replace( ptnTrailingReturn, ( all, term ) => `$$d["${attributeName}"] = ${term.trim()};` )}
  	}
  }
  		`;
  			} else {
  				sourceName = "$$s";
  			}
  		}
  
  		// append coerce() method of current attribute's type handler
  		{
  			const { args, body } = extractBody( handler.coerce );
  			if ( args.length < 2 ) {
  				throw new TypeError( `coerce() of ModelType for handling ${attribute.type} values must accept two arguments` );
  			}
  
  			deserialization[write++] = `
  {
  	let ${args[0]} = ${sourceName}["${attributeName}"];
  	const ${args[1]} = $$attrs["${attributeName}"];
  
  	{
  		${body.replace( ptnTrailingReturn, ( all, term ) => `$$d["${attributeName}"] = ${term.trim()};` )}
  	}
  }
  		`;
  		}
  	}
  
  	deserialization.splice( write );
  
  	// eslint-disable-next-line no-new-func
  	return new Function( "$$input", "$$attrs", `
  if ( !$$attrs || typeof $$attrs !== "object" ) {
  	throw new TypeError( "missing definition of attributes required for deserialization" );
  }
  
  const $$s = $$input && typeof $$input === "object" ? $$input : {};
  const $$d = {};
  
  ${deserialization.join( "" )}
  
  return $$d;
  ` );
  }