function protobufTypeToJsType(type) {
		switch (type) {
			case 'double':
			case 'float':
			case 'int32':
			case 'uint32':
			case 'sint32':
			case 'fixed32':
			case 'sfixed32':
				return 'number';

			case 'int64':
			case 'uint64':
			case 'sint64':
			case 'fixed64':
			case 'sfixed64':
				// 64-bit numbers are represented as strings
				return 'string';

			case 'bool':
				return 'boolean';

			case 'string':
				return 'string';

			case 'bytes':
				return 'Buffer';

			default:
				if (type[0] == '.') {
					// It's another protobuf msg, or an enum
					if (type[1] == 'E') {
						// It's an enum
						return type.substring(1);
					}

					return 'Proto' + type.replace(/\./g, '_');
				}

				throw new Error(`Unknown protobuf type ${type}`);
		}
	}
\n * @typedef {object} ${resolvedName}\n`;
		for (let j in obj[i].fields) {
			let type = protobufTypeToJsType(obj[i].fields[j].type);
			let name = j;

			if (type == 'number' && ['eresult', 'eResult', 'result'].includes(name)) {
				type = 'EResult';
			}

			if (OVERRIDE_TYPEDEF_TYPES[resolvedName] && OVERRIDE_TYPEDEF_TYPES[resolvedName][j]) {
				type = OVERRIDE_TYPEDEF_TYPES[resolvedName][j];
			}

			switch (obj[i].fields[j].rule) {
				case 'repeated':
					type += '[]';
					break;

				case 'required':
					break;

				default:
					// optional
					// Does this field have a default value?
					if (obj[i].fields[j].options && !['undefined', 'string'].includes(typeof obj[i].fields[j].options.default)) {
						name = `[${name}=${obj[i].fields[j].options.default}]`;
					} else {
						name = `[${name}]`;
					}
			}

			output += ` * @property {${type}} ${name}\n`;
		}
		output += '