export function transformType()

in modules/material-parser/src/parse/transform.ts [7:199]


export function transformType(itemType: any) {
  if (typeof itemType === 'string') return itemType;
  const {
    name,
    elements,
    value = elements,
    computed,
    required,
    type,
    raw,
    params,
    returns,
  } = itemType;
  if (computed !== undefined && value) {
    return safeEval(value);
  }
  const result: any = {
    type: name,
  };
  if (required) {
    result.isRequired = required;
  }
  switch (name) {
    case 'number':
    case 'string':
    case 'bool':
    case 'any':
    case 'symbol':
    case 'object':
    case 'null':
    case 'array':
    case 'element':
    case 'node':
    case 'void':
      break;
    case 'func':
      if (params) {
        result.params = params.map((x) => {
          const res: any = {
            name: x.name,
            propType: transformType(x.type || x.propType),
          };
          if (x.description) {
            res.description = x.description;
          }
          return res;
        });
      }
      if (returns) {
        result.returns = {
          propType: transformType(returns.type || returns.propType),
        };
      }
      if (raw) {
        result.raw = raw;
      }
      break;
    case 'literal': {
      result.type = 'oneOf';
      try {
        const literalValue = safeEval(value);
        result.value = [literalValue];
      } catch (e) {
        result.value = [raw];
      }
      break;
    }
    case 'enum':
    case 'oneOf':
      result.type = 'oneOf';
      result.value = value.map(transformType);
      break;
    case 'tuple':
      result.type = 'tuple';
      result.value = value.map(transformType);
      break;
    case 'union': {
      if (itemType.raw) {
        if (itemType.raw.match(/ReactNode$/)) {
          result.type = 'node';
          break;
        } else if (itemType.raw.match(/Element$/)) {
          result.type = 'element';
          break;
        }
      }
    }
    // eslint-disable-next-line no-fallthrough
    case 'oneOfType':
      result.type = 'oneOfType';
      result.value = value.map(transformType);
      break;
    case 'boolean':
      result.type = 'bool';
      break;
    case 'Function':
      result.type = 'func';
      break;
    case 'unknown':
      result.type = 'any';
      break;
    case 'Array':
    case 'arrayOf': {
      result.type = 'arrayOf';
      let _itemType = transformType(value[0]);
      if (typeof _itemType === 'object') {
        _itemType = omit(_itemType, ['isRequired']);
      }

      result.value = _itemType;
      break;
    }
    case 'signature': {
      if (typeof type === 'string') {
        result.type = type;
        break;
      }
      result.type = 'shape';
      const properties = type?.signature?.properties || itemType?.signature?.properties || [];
      if (properties.length === 0) {
        if (raw?.includes('=>')) {
          result.type = 'func';
          result.raw = raw;
        } else {
          result.type = 'object';
        }
      } else if (properties.length === 1 && typeof properties[0].key === 'object') {
        const v = transformType(properties[0].value);
        if (v === 'any') {
          result.type = 'object';
        } else if (typeof v === 'string') {
          result.value = v;
          result.type = 'objectOf';
        } else if (typeof v?.type === 'string') {
          result.value = v.type;
          result.type = 'objectOf';
        } else {
          result.type = 'object';
        }
      } else if (properties.length === 1 && properties[0].key === '__call') {
        result.type = 'func';
      } else {
        result.value = properties
          .filter((item: any) => typeof item.key !== 'object')
          .map((prop: any) => {
            const { key } = prop;
            const typeItem = {
              ...omit(prop.value, 'name'),
              type: prop.value.type || {},
            };
            typeItem.type = {
              ...typeItem.type,
              ...pick(prop.value, ['name', 'value']),
            };
            return transformItem(key, typeItem);
          });
      }
      break;
    }
    case 'objectOf':
    case 'instanceOf':
      result.value = transformType(value);
      break;
    case 'exact':
    case 'shape':
      result.value = Object.keys(value).map((n) => {
        const { name: _name, ...others } = value[n];
        return transformItem(n, {
          ...others,
          type: {
            name: _name,
          },
        });
      });
      break;
    case (name.match(/ReactNode$/) || {}).input:
      result.type = 'node';
      break;
    case (name.match(/JSX\.Element$/) || {}).input:
      result.type = 'element';
      break;
    default:
      result.type = 'object';
      break;
  }
  if (Object.keys(result).length === 1) {
    return result.type;
  }
  if (result?.type === 'oneOfType') {
    return combineOneOfValues(result);
  }
  return result;
}