diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.js
index 2b5b069e6..314c9c187 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.js
@@ -7,6 +7,11 @@
 //
 //////////////////////////////////////////////////////////////
 
+// import TypeSchema from './type.ui';
+import { getNodeListByName } from '../../../../../../../static/js/node_ajax';
+import { getNodePrivilegeRoleSchema } from '../../../../../static/js/privilege.ui';
+import TypeSchema, { getCompositeSchema, getRangeSchema, getExternalSchema, getDataTypeSchema } from './type.ui';
+
 define('pgadmin.node.type', [
   'sources/gettext', 'sources/url_for', 'jquery', 'underscore',
   'sources/pgadmin', 'pgadmin.browser', 'pgadmin.backform',
@@ -29,228 +34,6 @@ define('pgadmin.node.type', [
       });
   }
 
-  // Integer Cell for Columns Length and Precision
-  var IntegerDepCell = Backgrid.IntegerCell.extend({
-    initialize: function() {
-      Backgrid.NumberCell.prototype.initialize.apply(this, arguments);
-      Backgrid.Extension.DependentCell.prototype.initialize.apply(this, arguments);
-    },
-    dependentChanged: function () {
-      this.model.set(this.column.get('name'), null);
-      this.render();
-      return this;
-    },
-    remove: Backgrid.Extension.DependentCell.prototype.remove,
-  });
-
-  // Node-Ajax-Cell with Deps
-  var NodeAjaxOptionsDepsCell = Backgrid.Extension.NodeAjaxOptionsCell.extend({
-    initialize: function() {
-      Backgrid.Extension.NodeAjaxOptionsCell.prototype.initialize.apply(this, arguments);
-      Backgrid.Extension.DependentCell.prototype.initialize.apply(this, arguments);
-    },
-    dependentChanged: function () {
-      var model = this.model,
-        column = this.column,
-        editable = this.column.get('editable'),
-        input = this.$el.find('select').first();
-
-      var is_editable = _.isFunction(editable) ? !!editable.apply(column, [model]) : !!editable;
-      if (is_editable) {
-        this.$el.addClass('editable');
-        input.prop('disabled', false);
-      } else {
-        this.$el.removeClass('editable');
-        input.prop('disabled', true);
-      }
-
-      this.delegateEvents();
-      return this;
-    },
-    remove: Backgrid.Extension.DependentCell.prototype.remove,
-  });
-
-  // Composite type model declaration
-  var CompositeModel = Backform.CompositeModel = pgBrowser.Node.Model.extend({
-    idAttribute: 'attnum',
-    defaults: {
-      attnum: undefined,
-      member_name: undefined,
-      type: undefined,
-      tlength: undefined,
-      is_tlength: false,
-      precision: undefined,
-      is_precision: false,
-      collation: undefined,
-      min_val: undefined,
-      max_val: undefined,
-    },
-    type_options: undefined,
-    subtypes: undefined,
-    schema: [{
-      id: 'member_name', label: gettext('Member Name'),
-      type: 'text',  disabled: false, editable: true,
-    },{
-      id: 'type', label: gettext('Type'), control: 'node-ajax-options',
-      type: 'text', url: 'get_types', disabled: false, node: 'type',
-      cache_node: 'domain', editable: true,
-      cell: 'node-ajax-options', select2: {allowClear: false},
-      transform: function(d, control){
-        control.model.type_options =  d;
-        return d;
-      },
-    },{
-      // Note: There are ambiguities in the PG catalogs and docs between
-      // precision and scale. In the UI, we try to follow the docs as
-      // closely as possible, therefore we use Length/Precision and Scale
-      id: 'tlength', label: gettext('Length/Precision'), deps: ['type'], type: 'text',
-      disabled: false, cell: IntegerDepCell,
-      editable: function(m) {
-        // We will store type from selected from combobox
-        var of_type = m.get('type');
-        if(m.type_options) {
-          // iterating over all the types
-          _.each(m.type_options, function(o) {
-            // if type from selected from combobox matches in options
-            if ( of_type == o.value ) {
-              // if length is allowed for selected type
-              if(o.length)
-              {
-                // set the values in model
-                m.set('is_tlength', true, {silent: true});
-                m.set('min_val', o.min_val, {silent: true});
-                m.set('max_val', o.max_val, {silent: true});
-              } else {
-                // set the values in model
-                m.set('is_tlength', false, {silent: true});
-              }
-            }
-          });
-        }
-        return m.get('is_tlength');
-      },
-    },{
-      // Note: There are ambiguities in the PG catalogs and docs between
-      // precision and scale. In the UI, we try to follow the docs as
-      // closely as possible, therefore we use Length/Precision and Scale
-      id: 'precision', label: gettext('Scale'), deps: ['type'],
-      type: 'text', disabled: false, cell: IntegerDepCell,
-      editable: function(m) {
-        // We will store type from selected from combobox
-        var of_type = m.get('type');
-        if(m.type_options) {
-          // iterating over all the types
-          _.each(m.type_options, function(o) {
-            // if type from selected from combobox matches in options
-            if ( of_type == o.value ) {
-              // if precession is allowed for selected type
-              if(o.precision)
-              {
-                // set the values in model
-                m.set('is_precision', true, {silent: true});
-                m.set('min_val', o.min_val, {silent: true});
-                m.set('max_val', o.max_val, {silent: true});
-              } else {
-                // set the values in model
-                m.set('is_precision', false, {silent: true});
-              }
-            }
-          });
-        }
-        return m.get('is_precision');
-      },
-    },{
-      id: 'collation', label: gettext('Collation'),
-      cell: NodeAjaxOptionsDepsCell, deps: ['type'],
-      select2: {allowClear: false},
-      control: 'node-ajax-options', editable: function(m) {
-        var of_type = m.get('type'),
-          flag = false;
-        if(m.type_options) {
-          _.each(m.type_options, function(o) {
-            if ( of_type == o.value ) {
-              if(o.is_collatable)
-              {
-                flag = true;
-              }
-            }
-          });
-        }
-
-        if (flag) {
-          setTimeout(function(){
-            m.set('collspcname', '', {silent: true});
-          }, 10);
-        }
-        return flag;
-      },
-      type: 'text', disabled: false, url: 'get_collations', node: 'type',
-    }],
-    validate: function() {
-      var errmsg = null;
-
-      // Clearing previous errors first.
-      this.errorModel.clear();
-      // Validation for member name
-      if ( _.isUndefined(this.get('member_name')) ||
-        _.isNull(this.get('member_name')) ||
-          String(this.get('member_name')).replace(/^\s+|\s+$/g, '') == '') {
-        errmsg = gettext('Please specify the value for member name.');
-        this.errorModel.set('member_name', errmsg);
-        return errmsg;
-      }
-      else if ( _.isUndefined(this.get('type')) ||
-        _.isNull(this.get('type')) ||
-          String(this.get('type')).replace(/^\s+|\s+$/g, '') == '') {
-        errmsg = gettext('Please specify the type.');
-        this.errorModel.set('type', errmsg);
-        return errmsg;
-      }
-      // Validation for Length/Precision field (see comments above if confused about the naming!)
-      else if (this.get('is_tlength')
-        && !_.isUndefined(this.get('tlength'))) {
-        if (this.get('tlength') < this.get('min_val'))
-          errmsg = gettext('Length/Precision should not be less than %s.', this.get('min_val'));
-        if (this.get('tlength') > this.get('max_val') )
-          errmsg = gettext('Length/Precision should not be greater than %s.', this.get('max_val'));
-          // If we have any error set then throw it to user
-        if(errmsg) {
-          this.errorModel.set('tlength', errmsg);
-          return errmsg;
-        }
-      }
-      // Validation for scale field (see comments above if confused about the naming!)
-      else if (this.get('is_precision')
-        && !_.isUndefined(this.get('precision'))) {
-        if (this.get('precision') < this.get('min_val'))
-          errmsg = gettext('Scale should not be less than %s.', this.get('min_val'));
-        if (this.get('precision') > this.get('max_val'))
-          errmsg = gettext('Scale should not be greater than %s.', this.get('max_val'));
-          // If we have any error set then throw it to user
-        if(errmsg) {
-          this.errorModel.set('precision', errmsg);
-          return errmsg;
-        }
-      }
-      return null;
-    },
-  });
-
-  var EnumModel = Backform.EnumModel = pgBrowser.Node.Model.extend({
-    defaults: {
-      label: undefined,
-    },
-    schema: [{
-      id: 'label', label: gettext('Label'),type: 'text', disabled: false,
-      cellHeaderClasses: 'width_percent_99', editable: function(m) {
-        return _.isUndefined(m.get('label'));
-      },
-    }],
-    validate: function() {
-      return null;
-    },
-  });
-
   if (!pgBrowser.Nodes['type']) {
     pgBrowser.Nodes['type'] = schemaChild.SchemaChildNode.extend({
       type: 'type',
@@ -292,6 +75,9 @@ define('pgadmin.node.type', [
 
       },
       ext_funcs: undefined,
+      /* Few fields are kept since the properties tab for collection is not
+      yet migrated to new react schema. Once the properties for collection
+      is removed, remove this model */
       model: pgBrowser.Node.Model.extend({
         defaults: {
           name: undefined,
@@ -325,762 +111,38 @@ define('pgadmin.node.type', [
           control: 'node-list-by-name',
           type: 'text', mode: ['properties', 'create', 'edit'], node: 'role',
           disabled: 'inSchema', select2: {allowClear: false},
-        },{
-          id: 'schema', label: gettext('Schema'), cell: 'string',
-          type: 'text', mode: ['create', 'edit'], node: 'schema',
-          disabled: 'schemaCheck', filter: function(d) {
-            // If schema name start with pg_* then we need to exclude them
-            if(d && d.label.match(/^pg_/))
-            {
-              return false;
-            }
-            return true;
-          }, cache_node: 'database', cache_level: 'database',
-          control: 'node-list-by-name', select2: {allowClear: false},
-        },{
-          id: 'typtype', label: gettext('Type'),
-          mode: ['create','edit'], disabled: 'inSchema', readonly: 'inEditMode',
-          group: gettext('Definition'),
-          select2: { allowClear: false },
-          options: function() {
-            var typetype = [
-              {label: gettext('Composite'), value: 'c'},
-              {label: gettext('Enumeration'), value: 'e'},
-              {label: gettext('External'), value: 'b'},
-              {label: gettext('Range'), value: 'r'},
-              {label: gettext('Shell'), value: 'p'},
-            ];
-            if (this.node_info.server.server_type === 'ppas' &&
-            this.node_info.server.version >= 90500){
-              typetype.push(
-                {label: gettext('Nested Table'), value: 'N'},
-                {label: gettext('Varying Array'), value: 'V'}
-              );
-            }
-            return typetype;
-          },
-          // If create mode then by default open composite type
-          control: Backform.Select2Control.extend({
-            render: function(){
-              // Initialize parent's render method
-              Backform.Select2Control.prototype.render.apply(this, arguments);
-              if(this.model.isNew()) {
-                this.model.set({'typtype': 'c'});
-              }
-              return this;
-            },
-          }),
-        },{
-          id: 'composite', label: gettext('Composite Type'),
-          model: CompositeModel, editable: true, type: 'collection',
-          group: gettext('Definition'), mode: ['edit', 'create'],
-          control: 'unique-col-collection', uniqueCol : ['member_name'],
-          canAdd: true, canEdit: false, canDelete: true, disabled: 'inSchema',
-          deps: ['typtype'],
-          visible: function(m) {
-            return m.get('typtype') === 'c';
-          },
-        },{
-          id: 'enum', label: gettext('Enumeration type'),
-          model: EnumModel, editable: true, type: 'collection',
-          group: gettext('Definition'), mode: ['edit', 'create'],
-          canAdd: true, canEdit: false, canDelete: function(m) {
-            // We will disable it if it's in 'edit' mode
-            return m.isNew();
-          },
-          disabled: 'inSchema', deps: ['typtype'],
-          control: 'unique-col-collection', uniqueCol : ['label'],
-          visible: function(m) {
-            return m.get('typtype') === 'e';
-          },
-        },{
-          type: 'nested',
-          group: gettext('Definition'),
-          label: '',
-          control: 'plain-fieldset',
-          deps: ['typtype'],
-          mode: ['edit', 'create', 'properties'],
-          visible: function (m) {
-            return m.get('typtype') === 'N' || m.get('typtype') === 'V';
-          },
-          schema: [{
-            id: 'type',
-            type: 'text',
-            label: gettext('Data Type'),
-            group: gettext('Definition'),
-            control: 'node-ajax-options',
-            mode: ['edit', 'create','properties'],
-            readonly: 'inEditMode',
-            url: 'get_types',
-            disabled: false,
-            node: 'type',
-            cache_node: 'domain',
-            editable: true,
-            deps: ['typtype'],
-            cell: 'node-ajax-options',
-            select2: { allowClear: false },
-            transform: function (d, control) {
-              var data_types = [];
-              _.each(d, function (o) {
-                if (!(o.value.includes('[]'))) {
-                  data_types.push(o);
-                }
-              });
-              control.model.type_options = data_types;
-              return data_types;
-            },
-          },{
-            id: 'maxsize',
-            group: gettext('Definition'),
-            label: gettext('Size'),
-            type: 'int',
-            deps: ['typtype'],
-            cell: IntegerDepCell,
-            mode: ['create', 'edit','properties'],
-            readonly: 'inEditMode',
-            visible: function (m) {
-              return m.get('typtype') === 'V';
-            }
-          },{
-          // Note: There are ambiguities in the PG catalogs and docs between
-          // precision and scale. In the UI, we try to follow the docs as
-          // closely as possible, therefore we use Length/Precision and Scale
-            id: 'tlength',
-            group: gettext('Data Type'),
-            label: gettext('Length/Precision'),
-            mode: ['edit', 'create','properties'],
-            deps: ['type'],
-            type: 'text',
-            readonly: 'inEditMode',
-            cell: IntegerDepCell,
-            visible: function (m) {
-              return m.get('typtype') === 'N';
-            },
-            disabled: function (m) {
-              var of_type = m.get('type'),
-                flag = true;
-              _.each(m.type_options, function (o) {
-                if (of_type == o.value) {
-                  if (o.length) {
-                    m.set('min_val_attlen', o.min_val, { silent: true });
-                    m.set('max_val_attlen', o.max_val, { silent: true });
-                    flag = false;
-                  }
-                }
-              });
-              flag && setTimeout(function () {
-                if (m.get('attlen')) {
-                  m.set('attlen', null);
-                }
-              }, 10);
-              return flag;
-            },
-            editable: function (m) {
-              // We will store type from selected from combobox
-              var of_type = m.get('type');
-              if (m.type_options) {
-                // iterating over all the types
-                _.each(m.type_options, function (o) {
-                // if type from selected from combobox matches in options
-                  if (of_type == o.value) {
-                    // if length is allowed for selected type
-                    if (o.length) {
-                      // set the values in model
-                      m.set('is_tlength', true, { silent: true });
-                      m.set('min_val', o.min_val, { silent: true });
-                      m.set('max_val', o.max_val, { silent: true });
-                    } else {
-                      // set the values in model
-                      m.set('is_tlength', false, { silent: true });
-                    }
-                  }
-                });
-              }
-              return m.get('is_tlength');
-            }
-          },{
-            // Note: There are ambiguities in the PG catalogs and docs between
-            // precision and scale. In the UI, we try to follow the docs as
-            // closely as possible, therefore we use Length/Precision and Scale
-            id: 'precision',
-            group: gettext('Data Type'),
-            label: gettext('Scale'),
-            mode: ['edit', 'create','properties'],
-            deps: ['type'],
-            type: 'text',
-            readonly: 'inEditMode',
-            cell: IntegerDepCell,
-            visible: function (m) {
-              return m.get('typtype') === 'N';
-            },
-            disabled: function(m) {
-              var of_type = m.get('type'),
-                flag = true;
-              _.each(m.type_options, function(o) {
-                if ( of_type == o.value ) {
-                  if(o.precision) {
-                    m.set('min_val_attprecision', 0, {silent: true});
-                    m.set('max_val_attprecision', o.max_val, {silent: true});
-                    flag = false;
-                  }
-                }
-              });
-
-              flag && setTimeout(function() {
-                if(m.get('attprecision')) {
-                  m.set('attprecision', null);
-                }
-              },10);
-              return flag;
-            },
-            editable: function(m) {
-              // We will store type from selected from combobox
-              var of_type = m.get('type');
-              if(m.type_options) {
-                // iterating over all the types
-                _.each(m.type_options, function(o) {
-                  // if type from selected from combobox matches in options
-                  if ( of_type == o.value ) {
-                    // if precession is allowed for selected type
-                    if(o.precision)
-                    {
-                      // set the values in model
-                      m.set('is_precision', true, {silent: true});
-                      m.set('min_val', o.min_val, {silent: true});
-                      m.set('max_val', o.max_val, {silent: true});
-                    } else {
-                      // set the values in model
-                      m.set('is_precision', false, {silent: true});
-                    }
-                  }
-                });
-              }
-              return m.get('is_precision');
-            },
-          }]
-        },{
-          // We will disable range type control in edit mode
-          type: 'nested', control: 'plain-fieldset', group: gettext('Definition'),
-          mode: ['edit', 'create'],
-          visible: function(m) {
-            return m.get('typtype') === 'r';
-          }, deps: ['typtype'], label: '',
-          schema:[{
-            id: 'typname', label: gettext('Subtype'), cell: 'string',
-            control: 'node-ajax-options',
-            select2: { allowClear: true, placeholder: '', width: '100%' },
-            url: 'get_stypes', type: 'text', mode: ['properties', 'create', 'edit'],
-            group: gettext('Range Type'), disabled: 'inSchema',
-            readonly: 'inEditMode',
-            transform: function(d, self){
-              self.model.subtypes =  d;
-              return d;
-            },
-          },{
-            id: 'opcname', label: gettext('Subtype operator class'), cell: 'string',
-            mode: ['properties', 'create', 'edit'], group: gettext('Range Type'),
-            disabled: 'inSchema', readonly: 'inEditMode',  deps: ['typname'],
-            control: 'select2', options: function(control) {
-              var l_typname = control.model.get('typname'),
-                result = [];
-
-              if(!_.isUndefined(l_typname) && l_typname != '')
-              {
-                var node = control.field.get('schema_node'),
-                  _url = node.generate_url.apply(
-                    node, [
-                      null, 'get_subopclass', control.field.get('node_data'), false,
-                      control.field.get('node_info'),
-                    ]);
-                $.ajax({
-                  async: false,
-                  url: _url,
-                  cache: false,
-                  data: {'typname' : l_typname},
-                })
-                  .done(function(res) {
-                    result = res.data;
-                  })
-                  .fail(function() {
-                    control.model.trigger('pgadmin:view:fetch:error', control.model, control.field);
-                  });
-                //
-              }
-              return result;
-            },
-          },{
-            id: 'collname', label: gettext('Collation'), cell: 'string',
-            type: 'text', mode: ['properties', 'create', 'edit'],
-            group: gettext('Range Type'),
-            deps: ['typname'], control: 'node-ajax-options', url: 'get_collations',
-            select2: { allowClear: true, placeholder: '', width: '100%' },
-            disabled: function(m) {
-              if(this.node_info &&  'catalog' in this.node_info)
-              {
-                return true;
-              }
-
-              // Disbale in edit mode
-              if (!m.isNew()) {
-                return true;
-              }
-
-              // To check if collation is allowed?
-              var of_subtype = m.get('typname'),
-                is_collate = undefined;
-              if(!_.isUndefined(of_subtype)) {
-                // iterating over all the types
-                _.each(m.subtypes, function(s) {
-                  // if subtype from selected from combobox matches
-                  if ( of_subtype === s.label ) {
-                    // if collation is allowed for selected subtype
-                    // then enable it else disable it
-                    is_collate = s.is_collate;
-                  }
-                });
-              }
-              // If is_collate is true then do not disable
-              if(!is_collate) {
-                m.set({'collname': '', silent: true});
-                this.options = [];
-              }
-
-              return is_collate ? false : true;
-            },
-          },{
-            id: 'rngcanonical', label: gettext('Canonical function'), cell: 'string',
-            type: 'text', mode: ['properties', 'create', 'edit'],
-            group: gettext('Range Type'),
-            disabled: 'inSchema', readonly: 'inEditMode', deps: ['name', 'typname'],
-            control: 'select2', options: function(control) {
-              var name = control.model.get('name'),
-                result = [];
-
-              if(!_.isUndefined(name) && name != '')
-              {
-                var node = control.field.get('schema_node'),
-                  _url = node.generate_url.apply(
-                    node, [
-                      null, 'get_canonical', control.field.get('node_data'), false,
-                      control.field.get('node_info'),
-                    ]);
-                $.ajax({
-                  async: false,
-                  url: _url,
-                  cache: false,
-                  data: {'name' : name},
-                })
-                  .done(function(res) {
-                    result = res.data;
-                  })
-                  .fail(function() {
-                    control.model.trigger('pgadmin:view:fetch:error', control.model, control.field);
-                  });
-              }
-              return result;
-            },
-          },{
-            id: 'rngsubdiff', label: gettext('Subtype diff function'), cell: 'string',
-            type: 'text', mode: ['properties', 'create', 'edit'],
-            group: gettext('Range Type'),
-            disabled: 'inSchema', readonly: 'inEditMode', deps: ['typname', 'opcname'],
-            control: 'select2', options: function(control) {
-              var l_typname = control.model.get('typname'),
-                l_opcname = control.model.get('opcname'),
-                result = [];
-              this.options = [];
-              control.model.set({'rngsubdiff': [], silent: true});
-
-              if(!_.isUndefined(l_typname) && l_typname != '' &&
-                !_.isUndefined(l_opcname) && l_opcname != '') {
-                var node = control.field.get('schema_node'),
-                  _url = node.generate_url.apply(
-                    node, [
-                      null, 'get_stypediff',
-                      control.field.get('node_data'), false,
-                      control.field.get('node_info'),
-                    ]);
-                $.ajax({
-                  async: false,
-                  url: _url,
-                  cache: false,
-                  data: {'typname' : l_typname, 'opcname': l_opcname},
-                })
-                  .done(function(res) {
-                    result = res.data;
-                  })
-                  .fail(function() {
-                    control.model.trigger('pgadmin:view:fetch:error', control.model, control.field);
-                  });
-              }
-              return result;
-            },
-          }],
-        },{
-          type: 'nested', control: 'tab', group: gettext('Definition'),
-          label: gettext('External Type'), deps: ['typtype'],
-          mode: ['create', 'edit'], tabPanelExtraClasses:'inline-tab-panel-padded',
-          visible: function(m) {
-            return m.get('typtype') === 'b';
-          },
-          schema:[{
-            id: 'spacer_ctrl', group: gettext('Required'), mode: ['edit', 'create'], type: 'spacer',
-          },{
-            id: 'typinput', label: gettext('Input function'),
-            cell: 'string',type: 'text',
-            mode: ['properties', 'create', 'edit'], group: gettext('Required'),
-            disabled: 'inSchema', readonly: 'inEditMode',
-            control: 'node-ajax-options', url: 'get_external_functions',
-            transform: 'external_func_combo',
-            select2: { allowClear: true, placeholder: '', width: '100%' },
-          },{
-            id: 'typoutput', label: gettext('Output function'),
-            cell: 'string',
-            type: 'text', mode: ['properties', 'create', 'edit'],
-            group: gettext('Required'),
-            disabled: 'inSchema', readonly: 'inEditMode',
-            control: 'node-ajax-options', url: 'get_external_functions',
-            transform: 'external_func_combo',
-            select2: { allowClear: true, placeholder: '', width: '100%' },
-          },{
-            id: 'spacer_ctrl_optional_1', group: gettext('Optional-1'), mode: ['edit', 'create'], type: 'spacer',
-          },{
-            id: 'typreceive', label: gettext('Receive function'),
-            cell: 'string', type: 'text', group: gettext('Optional-1'),
-            mode: ['properties', 'create', 'edit'],
-            disabled: 'inSchema', readonly: 'inEditMode',
-            control: 'node-ajax-options', url: 'get_external_functions',
-            transform: 'external_func_combo',
-            select2: { allowClear: true, placeholder: '', width: '100%' },
-          },{
-            id: 'typsend', label: gettext('Send function'),
-            cell: 'string', group: gettext('Optional-1'),
-            type: 'text', mode: ['properties', 'create', 'edit'],
-            disabled: 'inSchema', readonly: 'inEditMode',
-            control: 'node-ajax-options', url: 'get_external_functions',
-            transform: 'external_func_combo',
-            select2: { allowClear: true, placeholder: '', width: '100%' },
-          },{
-            id: 'typmodin', label: gettext('Typmod in function'),
-            cell: 'string', type: 'text',
-            mode: ['properties', 'create', 'edit'], group: gettext('Optional-1'),
-            disabled: 'inSchema', readonly: 'inEditMode',
-            control: 'node-ajax-options', url: 'get_external_functions',
-            select2: { allowClear: true, placeholder: '', width: '100%' },
-            transform: function(d) {
-              var result = [{label :'', value : ''}];
-              _.each(d, function(item) {
-                // if type from selected from combobox matches in options
-                if ( item.cbtype === 'typmodin' || item.cbtype === 'all') {
-                  result.push(item);
-                }
-              });
-              return result;
-            },
-          },{
-            id: 'typmodout', label: gettext('Typmod out function'),
-            cell: 'string', group: gettext('Optional-1'),
-            type: 'text', mode: ['properties', 'create', 'edit'],
-            disabled: 'inSchema', readonly: 'inEditMode',
-            control: 'node-ajax-options', url: 'get_external_functions',
-            select2: { allowClear: true, placeholder: '', width: '100%' },
-            transform: function(d) {
-              var result = [{label :'', value : ''}];
-              _.each(d, function(item) {
-                // if type from selected from combobox matches in options
-                if ( item.cbtype === 'typmodout' || item.cbtype === 'all') {
-                  result.push(item);
-                }
-              });
-              return result;
-            },
-          },{
-            id: 'typlen', label: gettext('Internal length'),
-            cell: 'integer', group: gettext('Optional-1'),
-            type: 'int', mode: ['properties', 'create', 'edit'],
-            disabled: 'inSchema', readonly: 'inEditMode',
-          },{
-            id: 'variable', label: gettext('Variable?'), cell: 'switch',
-            group: gettext('Optional-1'), type: 'switch',
-            mode: ['create','edit'],
-            disabled: 'inSchema', readonly: 'inEditMode',
-          },{
-            id: 'typdefault', label: gettext('Default?'),
-            cell: 'string', group: gettext('Optional-1'),
-            type: 'text', mode: ['properties', 'create','edit'],
-            disabled: 'inSchema', readonly: 'inEditMode',
-          },{
-            id: 'typanalyze', label: gettext('Analyze function'),
-            cell: 'string', group: gettext('Optional-1'),
-            type: 'text', mode: ['properties', 'create','edit'],
-            disabled: 'inSchema', readonly: 'inEditMode',
-            control: 'node-ajax-options', url: 'get_external_functions',
-            transform: 'external_func_combo',
-            select2: { allowClear: true, placeholder: '', width: '100%' },
-          },{
-            id: 'typcategory', label: gettext('Category type'),
-            cell: 'string', group: gettext('Optional-1'),
-            type: 'text', mode: ['properties', 'create','edit'],
-            disabled: 'inSchema', readonly: 'inEditMode', control: 'select2',
-            select2: { allowClear: true, placeholder: '', width: '100%' },
-            options: [
-              {label :'', value : ''},
-              {label :'Array types', value : 'A'},
-              {label :'Boolean types', value : 'B'},
-              {label :'Composite types', value : 'C'},
-              {label :'Date/time types', value : 'D'},
-              {label :'Enum types', value : 'E'},
-              {label :'Geometric types', value : 'G'},
-              {label :'Network address types', value : 'I'},
-              {label :'Numeric types', value : 'N'},
-              {label :'Pseudo-types', value : 'P'},
-              {label :'String types', value : 'S'},
-              {label :'Timespan types', value : 'T'},
-              {label :'User-defined types', value : 'U'},
-              {label :'Bit-string types', value : 'V'},
-              {label :'unknown type', value : 'X'},
-            ],
-          },{
-            id: 'typispreferred', label: gettext('Preferred?'), cell: 'switch',
-            type: 'switch', mode: ['properties', 'create','edit'],
-            disabled: 'inSchema', readonly: 'inEditMode',
-            group: gettext('Optional-1'),
-          },{
-            id: 'spacer_ctrl_optional_2', group: gettext('Optional-2'), mode: ['edit', 'create'], type: 'spacer',
-          },{
-            id: 'element', label: gettext('Element type'), cell: 'string',
-            control: 'node-ajax-options', group: gettext('Optional-2'),
-            type: 'text', mode: ['properties', 'create', 'edit'],
-            disabled: 'inSchema', readonly: 'inEditMode', url: 'get_types',
-          },{
-            id: 'typdelim', label: gettext('Delimiter'), cell: 'string',
-            type: 'text', mode: ['properties', 'create', 'edit'],
-            group: gettext('Optional-2'), disabled: 'inSchema',
-            readonly: 'inEditMode',
-          },{
-            id: 'typalign', label: gettext('Alignment type'),
-            cell: 'string', group: gettext('Optional-2'),
-            type: 'text', mode: ['properties', 'create', 'edit'],
-            disabled: 'inSchema', readonly: 'inEditMode', control: 'select2',
-            select2: { allowClear: true, placeholder: '', width: '100%' },
-            options: [
-              {label :'', value : ''},
-              {label: 'char', value: 'c'},
-              {label: 'int2', value: 's'},
-              {label: 'int4', value: 'i'},
-              {label: 'double', value: 'd'},
-            ],
-          },{
-            id: 'typstorage', label: gettext('Storage type'),
-            type: 'text', mode: ['properties', 'create', 'edit'],
-            group: gettext('Optional-2'), cell: 'string',
-            disabled: 'inSchema', readonly: 'inEditMode', control: 'select2',
-            select2: { allowClear: true, placeholder: '', width: '100%' },
-            options: [
-              {label :'', value : ''},
-              {label: 'PLAIN', value: 'p'},
-              {label: 'EXTERNAL', value: 'e'},
-              {label: 'MAIN', value: 'm'},
-              {label: 'EXTENDED', value: 'x'},
-            ],
-          },{
-            id: 'typbyval', label: gettext('Passed by value?'),
-            cell: 'switch',
-            type: 'switch', mode: ['properties', 'create', 'edit'],
-            disabled: 'inSchema', readonly: 'inEditMode', group: gettext('Optional-2'),
-          },{
-            id: 'is_collatable', label: gettext('Collatable?'),
-            cell: 'switch',  min_version: 90100, group: gettext('Optional-2'),
-            type: 'switch', mode: ['properties', 'create', 'edit'],
-            disabled: 'inSchema', readonly: 'inEditMode',
-            // End of extension tab
-          }],
-        },{
-          id: 'alias', label: gettext('Alias'), cell: 'string',
-          type: 'text', mode: ['properties'],
-          disabled: 'inSchema',
-        }, pgBrowser.SecurityGroupSchema,{
-          id: 'type_acl', label: gettext('Privileges'), cell: 'string',
-          type: 'text', mode: ['properties'], group: 'security',
-          disabled: 'inSchema',
-        },{
-          id: 'member_list', label: gettext('Members'), cell: 'string',
-          type: 'text', mode: ['properties'], group: gettext('Definition'),
-          disabled: 'inSchema', visible: function(m) {
-            if(m.get('typtype') === 'c') {
-              return true;
-            }
-            return false;
-          },
-        },{
-          id: 'enum_list', label: gettext('Labels'), cell: 'string',
-          type: 'text', mode: ['properties'], group: gettext('Definition'),
-          disabled: 'inSchema', visible: function(m) {
-            if(m.get('typtype') === 'e') {
-              return true;
-            }
-            return false;
-          },
-        },{
-          id: 'is_sys_type', label: gettext('System type?'), cell: 'switch',
-          type: 'switch', mode: ['properties'],
-          disabled: 'inSchema',
-        },{
+        }, {
           id: 'description', label: gettext('Comment'), cell: 'string',
           type: 'multiline', mode: ['properties', 'create', 'edit'],
           disabled: 'inSchema',
-        },{
-          id: 'typacl', label: gettext('Privileges'), type: 'collection',
-          group: 'security', control: 'unique-col-collection',
-          model: pgBrowser.Node.PrivilegeRoleModel.extend({
-            privileges: ['U'],
-          }),
-          mode: ['edit', 'create'], canDelete: true,
-          uniqueCol : ['grantee'], deps: ['typtype'],
-          canAdd: function(m) {
-            // Do not allow to add when shell type is selected
-            // Clear acl & security label collections as well
-            if (m.get('typtype') === 'p') {
-              var acl = m.get('typacl');
-              if(acl.length > 0)
-                acl.reset();
-            }
-            return (m.get('typtype') !== 'p');
-          },
-        },{
-          id: 'seclabels', label: gettext('Security labels'),
-          model: pgBrowser.SecLabelModel, editable: false, type: 'collection',
-          group: 'security', mode: ['edit', 'create'],
-          min_version: 90100, canEdit: false, canDelete: true,
-          control: 'unique-col-collection', deps: ['typtype'],
-          canAdd: function(m) {
-            // Do not allow to add when shell type is selected
-            // Clear acl & security label collections as well
-            if (m.get('typtype') === 'p') {
-              var secLabs = m.get('seclabels');
-              if(secLabs.length > 0)
-                secLabs.reset();
-            }
-            return (m.get('typtype') !== 'p');
-          },
-        }],
-        validate: function() {
-          // Validation code for required fields
-          var msg;
-
-          this.errorModel.clear();
-
-          if (
-            _.isUndefined(this.get('name')) ||
-              _.isNull(this.get('name')) ||
-              String(this.get('name')).replace(/^\s+|\s+$/g, '') == ''
-          ) {
-            msg = gettext('Name cannot be empty.');
-            this.errorModel.set('name', msg);
-            return msg;
-          }
-
-          if (
-            _.isUndefined(this.get('schema')) ||
-              _.isNull(this.get('schema')) ||
-              String(this.get('schema')).replace(/^\s+|\s+$/g, '') == ''
-          ) {
-            msg = gettext('Schema cannot be empty.');
-            this.errorModel.set('schema', msg);
-            return msg;
-          }
-
-          if (
-            _.isUndefined(this.get('typtype')) ||
-              _.isNull(this.get('typtype')) ||
-              String(this.get('typtype')).replace(/^\s+|\s+$/g, '') == ''
-          ) {
-            msg = gettext('Type cannot be empty.');
-            this.errorModel.set('typtype', msg);
-            return msg;
-          }
-
-          // For Range
-          if(this.get('typtype') == 'r') {
-            if (
-              _.isUndefined(this.get('typname')) ||
-                _.isNull(this.get('typname')) ||
-                String(this.get('typname')).replace(/^\s+|\s+$/g, '') == ''
-            ) {
-              msg = gettext('Subtype name cannot be empty.');
-              this.errorModel.set('typname', msg);
-              return msg;
-            }
-          }
-
-          // For External
-          if(this.get('typtype') == 'b') {
-            if (
-              _.isUndefined(this.get('typinput')) ||
-                _.isNull(this.get('typinput')) ||
-                String(this.get('typinput')).replace(/^\s+|\s+$/g, '') == ''
-            ) {
-              msg = gettext('Input function cannot be empty.');
-              this.errorModel.set('typinput', msg);
-              return msg;
-            }
-            if (
-              _.isUndefined(this.get('typoutput')) ||
-                _.isNull(this.get('typoutput')) ||
-                String(this.get('typoutput')).replace(/^\s+|\s+$/g, '') == ''
-            ) {
-              msg = gettext('Output function cannot be empty.');
-              this.errorModel.set('typoutput', msg);
-              return msg;
-            }
-          }
-
-          // For Nested Table and Varying Array
-          if(this.get('typtype') == 'N' || this.get('typtype') == 'V') {
-            if (_.isUndefined(this.get('type')) || _.isNull(this.get('type')) ||
-                String(this.get('type')).replace(/^\s+|\s+$/g, '') == '') {
-              msg = gettext('Data type cannot be empty.');
-              this.errorModel.set('type', msg);
-              return msg;
-            }
-          }
-
-          return null;
-        },
-        // We will disable everything if we are under catalog node
-        inSchema: function() {
-          if(this.node_info &&  'catalog' in this.node_info)
+        }]
+      }),
+      getSchema: (treeNodeInfo, itemNodeData) => {
+        let nodeObj = pgAdmin.Browser.Nodes['type'];
+        return new TypeSchema(
+          (privileges)=>getNodePrivilegeRoleSchema(nodeObj, treeNodeInfo, itemNodeData, privileges),
+          ()=>getCompositeSchema(nodeObj, treeNodeInfo, itemNodeData),
+          ()=>getRangeSchema(nodeObj, treeNodeInfo, itemNodeData),
+          ()=>getExternalSchema(nodeObj, treeNodeInfo, itemNodeData),
+          ()=>getDataTypeSchema(nodeObj, treeNodeInfo, itemNodeData),
           {
-            return true;
-          }
-          return false;
-        },
-        inEditMode: function(m) {
-          return !m.isNew();
-        },
-        schemaCheck: function(m) {
-          if(this.node_info && 'schema' in this.node_info)
+            roles:() => getNodeListByName('role', treeNodeInfo, itemNodeData, {
+              cacheLevel: 'database'
+            }),
+            schemas:() => getNodeListByName('schema', treeNodeInfo, itemNodeData, {
+              cacheLevel: 'database'
+            }),
+            server_info: pgBrowser.serverInfo[treeNodeInfo.server._id],
+            node_info: treeNodeInfo
+          },
           {
-            if (m.isNew()) {
-              return false;
-            } else {
-              return m.get('typtype') === 'p';
-            }
+            typeowner: pgBrowser.serverInfo[treeNodeInfo.server._id].user.name,
+            schema: 'catalog' in treeNodeInfo ? treeNodeInfo.catalog.label : treeNodeInfo.schema.label,
+            // If create mode then by default open composite type
+            typtype: 'c'
           }
-          return true;
-        },
-        // Function will help us to fill combobox
-        external_func_combo: function(d) {
-          var result = [];
-          _.each(d, function(item) {
-            // if type from selected from combobox matches in options
-            if ( item.cbtype == 'all' ) {
-              result.push(item);
-            }
-          });
-          return result;
-        },
-      }),
+        );
+      }
     });
   }
   return pgBrowser.Nodes['type'];
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.ui.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.ui.js
new file mode 100644
index 000000000..50c6d0a5f
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.ui.js
@@ -0,0 +1,1640 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2021, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import gettext from 'sources/gettext';
+import BaseUISchema from 'sources/SchemaView/base_schema.ui';
+import SecLabelSchema from '../../../../../static/js/sec_label.ui';
+
+import { getNodeAjaxOptions } from '../../../../../../../static/js/node_ajax';
+import _ from 'underscore';
+import getApiInstance from 'sources/api_instance';
+import { isEmptyString, integerValidator } from 'sources/validators';
+
+
+function getCompositeSchema(nodeObj, treeNodeInfo, itemNodeData) {
+  return new CompositeSchema(
+    {
+      types: () => getNodeAjaxOptions('get_types', nodeObj, treeNodeInfo, itemNodeData, {
+        cacheLevel: 'domain'
+      }),
+      collations: () => getNodeAjaxOptions('get_collations', nodeObj, treeNodeInfo, itemNodeData)
+    }
+  );
+}
+
+function getRangeSchema(nodeObj, treeNodeInfo, itemNodeData) {
+  return new RangeSchema(
+    {
+      typnameList: () => getNodeAjaxOptions('get_stypes', nodeObj, treeNodeInfo, itemNodeData),
+      getSubOpClass: (typname) => {
+        return new Promise((resolve, reject)=>{
+          const api = getApiInstance();
+
+          var _url = nodeObj.generate_url.apply(
+            nodeObj, [
+              null, 'get_subopclass', itemNodeData, false,
+              treeNodeInfo,
+            ]);
+          var data;
+
+          if(!_.isUndefined(typname) && typname != ''){
+            api.get(_url, {
+              params: {
+                'typname' : typname
+              }
+            }).then(res=>{
+              data = res.data.data;
+              resolve(data);
+            }).catch((err)=>{
+              reject(err);
+            });
+          }
+        });
+      },
+      collationsList: () => getNodeAjaxOptions('get_collations', nodeObj, treeNodeInfo, itemNodeData),
+      getCanonicalFunctions: (name) => {
+        return new Promise((resolve, reject)=>{
+          const api = getApiInstance();
+
+          var _url = nodeObj.generate_url.apply(
+            nodeObj, [
+              null, 'get_canonical', itemNodeData, false,
+              treeNodeInfo,
+            ]);
+          var data;
+
+          if(!_.isUndefined(name) && name != ''){
+            api.get(_url, {
+              params: {
+                'name' : name
+              }
+            }).then(res=>{
+              data = res.data.data;
+              resolve(data);
+            }).catch((err)=>{
+              reject(err);
+            });
+          }
+        });
+      },
+      getSubDiffFunctions: (typname, opcname) => {
+        return new Promise((resolve, reject)=>{
+          const api = getApiInstance();
+
+          var _url = nodeObj.generate_url.apply(
+            nodeObj, [
+              null, 'get_stypediff', itemNodeData, false,
+              treeNodeInfo,
+            ]);
+          var data;
+
+          if(!_.isUndefined(typname) && typname != '' &&
+              !_.isUndefined(opcname) && opcname != ''){
+            api.get(_url, {
+              params: {
+                'typname' : typname,
+                'opcname': opcname
+              }
+            }).then(res=>{
+              data = res.data.data;
+              resolve(data);
+            }).catch((err)=>{
+              reject(err);
+            });
+          }
+        });
+      },
+    }, {
+      node_info: treeNodeInfo
+    }
+  );
+}
+
+function getExternalSchema(nodeObj, treeNodeInfo, itemNodeData) {
+  return new ExternalSchema(
+    {
+      externalFunctionsList: () => getNodeAjaxOptions('get_external_functions', nodeObj, treeNodeInfo, itemNodeData),
+      types: () => getNodeAjaxOptions('get_types', nodeObj, treeNodeInfo, itemNodeData, {
+        cacheLevel: 'domain'
+      })
+    }, {
+      node_info: treeNodeInfo
+    }
+  );
+}
+
+function getDataTypeSchema(nodeObj, treeNodeInfo, itemNodeData) {
+  return new DataTypeSchema(
+    {
+      types: () => getNodeAjaxOptions('get_types', nodeObj, treeNodeInfo, itemNodeData, {
+        cacheLevel: 'domain'
+      })
+    }
+  );
+}
+
+class EnumerationSchema extends BaseUISchema {
+
+  constructor() {
+    super({
+      oid: undefined,
+      label: undefined,
+    });
+  }
+
+  get idAttribute() {
+    return 'oid';
+  }
+
+  get baseFields() {
+    var obj = this;
+    return [
+      {
+        id: 'label', label: gettext('Label'),
+        type: 'text',  cell: 'text',
+        cellHeaderClasses: 'width_percent_99',
+        readonly: function (state) {
+          return !obj.isNew(state);
+        },
+      }
+    ];
+  }
+}
+
+class RangeSchema extends BaseUISchema {
+  constructor(fieldOptions = {}, node_info, initValues) {
+    super({
+      typname: null,
+      oid: undefined,
+      is_sys_type: false,
+      ...initValues
+    });
+    this.fieldOptions = {
+      typnameList: [],
+      collationsList: [],
+      ...fieldOptions
+    };
+    this.node_info = {
+      ...node_info.node_info
+    };
+  }
+
+  get idAttribute() {
+    return 'oid';
+  }
+
+  get baseFields() {
+    var obj = this;
+    return [{
+      // We will disable range type control in edit mode
+      id: 'typname', label: gettext('Subtype'),
+      type: (state) => {
+        return {
+          type: 'select',
+          options: obj.fieldOptions.typnameList,
+          optionsLoaded: (options) => { obj.fieldOptions.typnameList = options; },
+          controlProps: {
+            allowClear: true,
+            filter: (options) => {
+              let res = [];
+              if (state && obj.isNew(state)) {
+                if(options && options.length > 0) {
+                  state.subtypes = options;
+                }
+                options.forEach((option) => {
+                  if(option && option.label == '') {
+                    return;
+                  }
+                  res.push({ label: option.label, value: option.value });
+                });
+              } else {
+                res = options;
+              }
+              return res;
+            }
+          }
+        };
+      },
+      controlProps: { allowClear: true, placeholder: '', width: '100%' },
+      mode: ['properties', 'create', 'edit'],
+      group: gettext('Range Type'),
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+    }, {
+      id: 'opcname', label: gettext('Subtype operator class'), cell: 'string',
+      mode: ['properties', 'create', 'edit'], group: gettext('Range Type'),
+      disabled: () => inSchema(obj.node_info),
+      readonly: function(state) {
+        return !obj.isNew(state);
+      },
+      deps: ['typname'],
+      type: (state)=>{
+        return {
+          type: 'select',
+          options: () => obj.fieldOptions.getSubOpClass(state.typname),
+          optionsReloadBasis: state.typname,
+          controlProps: {
+            allowClear: true,
+            filter: (options) => {
+              let res = [];
+              if (state) {
+                options.forEach((option) => {
+                  if(option && option.label == '') {
+                    return;
+                  }
+                  res.push({ label: option.label, value: option.value });
+                });
+              } else {
+                res = options;
+              }
+              return res;
+            }
+          }
+        };
+      },
+    }, {
+      id: 'collname', label: gettext('Collation'), cell: 'string',
+      type: (state) => {
+        return {
+          type: 'select',
+          options: obj.fieldOptions.collationsList,
+          optionsLoaded: (options) => { obj.fieldOptions.collationsList = options; },
+          controlProps: {
+            allowClear: true,
+            placeholder: '',
+            width: '100%',
+            filter: (options) => {
+              let res = [];
+              if (state && obj.isNew(state)) {
+                options.forEach((option) => {
+                  if(option && option.label == '') {
+                    return;
+                  }
+                  res.push({ label: option.label, value: option.value });
+                });
+              } else {
+                res = options;
+              }
+              return res;
+            }
+          }
+        };
+      },
+      mode: ['properties', 'create', 'edit'],
+      group: gettext('Range Type'),
+      deps: ['typname'],
+      controlProps: { allowClear: true, placeholder: '', width: '100%' },
+      disabled: (state) => {
+        let disableCollNameControl = inSchema(obj.node_info);
+        if (disableCollNameControl)
+          return disableCollNameControl;
+
+        // To check if collation is allowed?
+        var of_subtype = state.typname;
+        if(!_.isUndefined(of_subtype)) {
+          // iterating over all the types
+          _.each(state.subtypes, function(s) {
+            // if subtype from selected from combobox matches
+            if ( of_subtype === s.label ) {
+              // if collation is allowed for selected subtype
+              // then enable it else disable it
+              disableCollNameControl = s.is_collate;
+            }
+          });
+        }
+        // If is_collate is true then do not disable
+        if(!disableCollNameControl) {
+          state.collname = '';
+          this.options = [];
+        }
+
+        return disableCollNameControl ? false : true;
+      },
+      readonly: function(state) {
+        return !obj.isNew(state);
+      }
+    }, {
+      id: 'rngcanonical', label: gettext('Canonical function'), cell: 'string',
+      type: (state)=>{
+        return {
+          type: 'select',
+          options: () => obj.fieldOptions.getCanonicalFunctions(state.name),
+          optionsReloadBasis: state.typname,
+          controlProps: {
+            allowClear: true,
+            filter: (options) => {
+              let res = [];
+              if (state) {
+                options.forEach((option) => {
+                  if(option && option.label == '') {
+                    return;
+                  }
+                  res.push({ label: option.label, value: option.value });
+                });
+              } else {
+                res = options;
+              }
+              return res;
+            }
+          }
+        };
+      },
+      mode: ['properties', 'create', 'edit'],
+      group: gettext('Range Type'),
+      disabled: () => inSchema(obj.node_info),
+      readonly: function(state) {
+        return !obj.isNew(state);
+      },
+      deps: ['name', 'typname'],
+    }, {
+      id: 'rngsubdiff', label: gettext('Subtype diff function'), cell: 'string',
+      mode: ['properties', 'create', 'edit'],
+      group: gettext('Range Type'),
+      disabled: () => inSchema(obj.node_info),
+      readonly: function(state) {
+        return !obj.isNew(state);
+      },
+      deps: ['typname', 'opcname'],
+      type: (state)=>{
+        let fetchOptionsBasis = state.typname + state.opcname;
+        return {
+          type: 'select',
+          options: () => obj.fieldOptions.getSubDiffFunctions(state.typname, state.opcname),
+          optionsReloadBasis: fetchOptionsBasis,
+          controlProps: {
+            allowClear: true,
+            filter: (options) => {
+              let res = [];
+              if (state) {
+                options.forEach((option) => {
+                  if(option && option.label == '') {
+                    return;
+                  }
+                  res.push({ label: option.label, value: option.value });
+                });
+              } else {
+                res = options;
+              }
+              return res;
+            }
+          }
+        };
+      },
+    }
+    ];
+  }
+
+  validate(state, setError) {
+
+    let errmsg = null;
+
+    if(state.typtype === 'r') {
+      if (isEmptyString(state.typname)) {
+        errmsg = gettext('Subtype cannot be empty');
+        setError('typname', errmsg);
+        return true;
+      }
+    }
+  }
+}
+
+class ExternalSchema extends BaseUISchema {
+  constructor(fieldOptions = {}, node_info, initValues) {
+    super({
+      name: null,
+      typinput: undefined,
+      oid: undefined,
+      is_sys_type: false,
+      typtype: undefined,
+      ...initValues
+    });
+    this.fieldOptions = {
+      types: [],
+      externalFunctionsList: [],
+      ...fieldOptions
+    };
+    this.fieldOptions.typeCategory = [
+      {label :'Array types', value : 'A'},
+      {label :'Boolean types', value : 'B'},
+      {label :'Composite types', value : 'C'},
+      {label :'Date/time types', value : 'D'},
+      {label :'Enum types', value : 'E'},
+      {label :'Geometric types', value : 'G'},
+      {label :'Network address types', value : 'I'},
+      {label :'Numeric types', value : 'N'},
+      {label :'Pseudo-types', value : 'P'},
+      {label :'String types', value : 'S'},
+      {label :'Timespan types', value : 'T'},
+      {label :'User-defined types', value : 'U'},
+      {label :'Bit-string types', value : 'V'},
+      {label :'unknown type', value : 'X'},
+    ];
+    this.fieldOptions.typeAlignOptions = [
+      {label: 'char', value: 'c'},
+      {label: 'int2', value: 's'},
+      {label: 'int4', value: 'i'},
+      {label: 'double', value: 'd'},
+    ];
+    this.fieldOptions.typStorageOptions = [
+      {label: 'PLAIN', value: 'p'},
+      {label: 'EXTERNAL', value: 'e'},
+      {label: 'MAIN', value: 'm'},
+      {label: 'EXTENDED', value: 'x'},
+    ];
+    this.node_info = {
+      ...node_info.node_info
+    };
+  }
+
+  get idAttribute() {
+    return 'oid';
+  }
+
+  // Function will help us to fill combobox
+  external_func_combo(control) {
+    var result = [];
+    _.each(control, function(item) {
+
+      if(item && item.label == '') {
+        return;
+      }
+      // if type from selected from combobox matches in options
+      if ( item.cbtype == 'all' ) {
+        result.push(item);
+      }
+    });
+    return result;
+  }
+
+  get baseFields() {
+    var obj = this;
+    return [{
+      id: 'spacer_ctrl', group: gettext('Required'), mode: ['edit', 'create'], type: 'spacer',
+    },{
+      id: 'typinput', label: gettext('Input function'),
+      mode: ['properties', 'create', 'edit'], group: gettext('Required'),
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+      type: (state) => {
+        return {
+          type: 'select',
+          options: obj.fieldOptions.externalFunctionsList,
+          optionsLoaded: (options) => { obj.fieldOptions.externalFunctionsList = options; },
+          controlProps: {
+            allowClear: true,
+            placeholder: '',
+            width: '100%',
+            filter: (options) => {
+              let res = [];
+              if (state && obj.isNew(state)) {
+                res = obj.external_func_combo(options);
+              } else {
+                res = options;
+              }
+              return res;
+            }
+          }
+        };
+      },
+    }, {
+      id: 'typoutput', label: gettext('Output function'),
+      mode: ['properties', 'create', 'edit'],
+      group: gettext('Required'),
+      type: (state) => {
+        return {
+          type: 'select',
+          options: obj.fieldOptions.externalFunctionsList,
+          optionsLoaded: (options) => { obj.fieldOptions.externalFunctionsList = options; },
+          controlProps: {
+            allowClear: true,
+            placeholder: '',
+            width: '100%',
+            filter: (options) => {
+              let res = [];
+              if (state && obj.isNew(state)) {
+                res = obj.external_func_combo(options);
+              } else {
+                res = options;
+              }
+              return res;
+            }
+          }
+        };
+      },
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+      disabled: () => inSchema(obj.node_info),
+      controlProps: { allowClear: true, placeholder: '', width: '100%' },
+    },{
+      id: 'spacer_ctrl_optional_1', group: gettext('Optional-1'), mode: ['edit', 'create'], type: 'spacer',
+    },{
+      id: 'typreceive', label: gettext('Receive function'),
+      type: (state) => {
+        return {
+          type: 'select',
+          options: obj.fieldOptions.externalFunctionsList,
+          optionsLoaded: (options) => { obj.fieldOptions.externalFunctionsList = options; },
+          controlProps: {
+            allowClear: true,
+            placeholder: '',
+            width: '100%',
+            filter: (options) => {
+              let res = [];
+              if (state && obj.isNew(state)) {
+                res = obj.external_func_combo(options);
+              } else {
+                res = options;
+              }
+              return res;
+            }
+          }
+        };
+      },
+      group: gettext('Optional-1'),
+      mode: ['properties', 'create', 'edit'],
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+      controlProps: { allowClear: true, placeholder: '', width: '100%' },
+    },{
+      id: 'typsend', label: gettext('Send function'),
+      group: gettext('Optional-1'),
+      type: (state) => {
+        return {
+          type: 'select',
+          options: obj.fieldOptions.externalFunctionsList,
+          optionsLoaded: (options) => { obj.fieldOptions.externalFunctionsList = options; },
+          controlProps: {
+            allowClear: true,
+            placeholder: '',
+            width: '100%',
+            filter: (options) => {
+              let res = [];
+              if (state && obj.isNew(state)) {
+                res = obj.external_func_combo(options);
+              } else {
+                res = options;
+              }
+              return res;
+            }
+          }
+        };
+      },
+      mode: ['properties', 'create', 'edit'],
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+      controlProps: { allowClear: true, placeholder: '', width: '100%' },
+    },{
+      id: 'typmodin', label: gettext('Typmod in function'),
+      type: (state) => {
+        return {
+          type: 'select',
+          options: obj.fieldOptions.externalFunctionsList,
+          optionsLoaded: (options) => { obj.fieldOptions.externalFunctionsList = options; },
+          controlProps: {
+            allowClear: true,
+            placeholder: '',
+            width: '100%',
+            filter: (options) => {
+              let res = [];
+              if (state && obj.isNew(state)) {
+                _.each(options, function(item) {
+                  if(item && item.label == '') {
+                    return;
+                  }
+                  // if type from selected from combobox matches in options
+                  if ( item.cbtype === 'typmodin' || item.cbtype === 'all') {
+                    res.push(item);
+                  }
+                });
+              } else {
+                res = options;
+              }
+              return res;
+            }
+          }
+        };
+      },
+      mode: ['properties', 'create', 'edit'], group: gettext('Optional-1'),
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+      controlProps: { allowClear: true, placeholder: '', width: '100%' },
+    },{
+      id: 'typmodout', label: gettext('Typmod out function'),
+      group: gettext('Optional-1'),
+      type: (state) => {
+        return {
+          type: 'select',
+          options: obj.fieldOptions.externalFunctionsList,
+          optionsLoaded: (options) => { obj.fieldOptions.externalFunctionsList = options; },
+          controlProps: {
+            allowClear: true,
+            placeholder: '',
+            width: '100%',
+            filter: (options) => {
+              let res = [];
+              if (state && obj.isNew(state)) {
+                _.each(options, function(item) {
+                  if(item && item.label == '') {
+                    return;
+                  }
+                  // if type from selected from combobox matches in options
+                  if ( item.cbtype === 'typmodout' || item.cbtype === 'all') {
+                    res.push(item);
+                  }
+                });
+              } else {
+                res = options;
+              }
+              return res;
+            }
+          }
+        };
+      },
+      mode: ['properties', 'create', 'edit'],
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+    },{
+      id: 'typlen', label: gettext('Internal length'),
+      cell: 'integer', group: gettext('Optional-1'),
+      type: 'int', mode: ['properties', 'create', 'edit'],
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+    },{
+      id: 'variable', label: gettext('Variable?'), cell: 'switch',
+      group: gettext('Optional-1'), type: 'switch',
+      mode: ['create','edit'],
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+    },{
+      id: 'typdefault', label: gettext('Default?'),
+      cell: 'string', group: gettext('Optional-1'),
+      type: 'text', mode: ['properties', 'create','edit'],
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+    },{
+      id: 'typanalyze', label: gettext('Analyze function'),
+      group: gettext('Optional-1'),
+      type: (state) => {
+        return {
+          type: 'select',
+          options: obj.fieldOptions.externalFunctionsList,
+          optionsLoaded: (options) => { obj.fieldOptions.externalFunctionsList = options; },
+          controlProps: {
+            allowClear: true,
+            placeholder: '',
+            width: '100%',
+            filter: (options) => {
+              let res = [];
+              if (state && obj.isNew(state)) {
+                res = obj.external_func_combo(options);
+              } else {
+                res = options;
+              }
+              return res;
+            }
+          }
+        };
+      },
+      mode: ['properties', 'create','edit'],
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+      controlProps: { allowClear: true, placeholder: '', width: '100%' },
+    },{
+      id: 'typcategory', label: gettext('Category type'),
+      cell: 'string',
+      group: gettext('Optional-1'),
+      type: () => {
+        return {
+          type: 'select',
+          options: obj.fieldOptions.typeCategory,
+          optionsLoaded: (options) => { obj.fieldOptions.typeCategory = options; },
+          controlProps: {
+            allowClear: true,
+            placeholder: '',
+            width: '100%',
+          }
+        };
+      },
+      mode: ['properties', 'create','edit'],
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+      controlProps: { allowClear: true, placeholder: '', width: '100%' },
+    },{
+      id: 'typispreferred', label: gettext('Preferred?'),
+      type: 'switch', mode: ['properties', 'create','edit'],
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+      group: gettext('Optional-1'),
+    },{
+      id: 'spacer_ctrl_optional_2', group: gettext('Optional-2'), mode: ['edit', 'create'], type: 'spacer',
+    },{
+      id: 'element', label: gettext('Element type'),
+      group: gettext('Optional-2'),
+      type: (state) => {
+        return {
+          type: 'select',
+          options: obj.fieldOptions.types,
+          controlProps: {
+            allowClear: true,
+            placeholder: '',
+            width: '100%',
+            filter: (options) => {
+              let res = [];
+              if (state && obj.isNew(state)) {
+                _.each(options, function(item) {
+                  if(item && item.label == '') {
+                    return;
+                  }
+                  // if type from selected from combobox matches in options
+                  res.push(item);
+                });
+              } else {
+                res = options;
+              }
+              return res;
+            }
+          }
+        };
+      },
+      mode: ['properties', 'create', 'edit'],
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+    },{
+      id: 'typdelim', label: gettext('Delimiter'),
+      cell: 'string',
+      type: 'text',
+      mode: ['properties', 'create', 'edit'],
+      group: gettext('Optional-2'),
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+    },{
+      id: 'typalign', label: gettext('Alignment type'),
+      cell: 'string', group: gettext('Optional-2'),
+      type: 'select',
+      options: obj.fieldOptions.typeAlignOptions,
+      mode: ['properties', 'create', 'edit'],
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+      controlProps: { allowClear: true, placeholder: '', width: '100%' },
+    },{
+      id: 'typstorage', label: gettext('Storage type'),
+      type: 'select', mode: ['properties', 'create', 'edit'],
+      group: gettext('Optional-2'), cell: 'string',
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+      controlProps: { allowClear: true, placeholder: '', width: '100%' },
+      options: obj.fieldOptions.typStorageOptions,
+    },{
+      id: 'typbyval', label: gettext('Passed by value?'),
+      cell: 'switch',
+      type: 'switch', mode: ['properties', 'create', 'edit'],
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+      group: gettext('Optional-2'),
+    },{
+      id: 'is_collatable', label: gettext('Collatable?'),
+      cell: 'switch',  min_version: 90100, group: gettext('Optional-2'),
+      type: 'switch', mode: ['properties', 'create', 'edit'],
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+      // End of extension tab
+    }];
+  }
+
+  validate(state, setError) {
+
+    let errmsg = null;
+
+    if(state.typtype === 'b') {
+
+      if (isEmptyString(state.typinput)) {
+        errmsg = gettext('Input function cannot be empty');
+        setError('typinput', errmsg);
+        return true;
+      }
+
+      if (isEmptyString(state.typoutput)) {
+        errmsg = gettext('Output function cannot be empty');
+        setError('typoutput', errmsg);
+        return true;
+      }
+    }
+    return false;
+  }
+}
+
+class CompositeSchema extends BaseUISchema {
+  constructor(fieldOptions = {}, initValues) {
+    super({
+      oid: undefined,
+      is_sys_type: false,
+      attnum: undefined,
+      member_name: undefined,
+      type: undefined,
+      tlength: null,
+      is_tlength: false,
+      precision: undefined,
+      is_precision: false,
+      collation: undefined,
+      min_val: undefined,
+      max_val: undefined,
+      ...initValues
+    });
+    this.fieldOptions = {
+      types: [],
+      collations: [],
+      ...fieldOptions
+    };
+    this.type_options = {};
+  }
+
+  setTypeOptions(options) {
+    options.forEach((option)=>{
+      this.type_options[option.value] = {
+        ...option,
+      };
+    });
+  }
+
+  get idAttribute() {
+    return 'oid';
+  }
+
+  get baseFields() {
+    var obj = this;
+    return [{
+      id: 'member_name', label: gettext('Member Name'),
+      type: 'text', cell: 'text'
+    },
+    {
+      id: 'type', label: gettext('Type'),
+      type: 'text',
+      cell: ()=>({
+        cell: 'select', options: obj.fieldOptions.types,
+        optionsLoaded: (options)=>{obj.setTypeOptions(options);},
+        controlProps: {
+          allowClear: false,
+        }
+      }),
+    }, {
+      // Note: There are ambiguities in the PG catalogs and docs between
+      // precision and scale. In the UI, we try to follow the docs as
+      // closely as possible, therefore we use Length/Precision and Scale
+      id: 'tlength', label: gettext('Length/Precision'), deps: ['type'], type: 'text',
+      disabled: false,
+      cell: 'int',
+      depChange: (state, changeSource)=>{
+        if(_.isArray(changeSource) && changeSource[2] == 'type') {
+          state.tlength = null;
+          return {...state
+            , value: null
+          };
+        }
+      },
+      editable: (state) => {
+        // We will store type from selected from combobox
+        var of_type = state.type;
+        if(obj.type_options) {
+          // iterating over all the types
+          _.each(obj.type_options, function(o) {
+            // if type from selected from combobox matches in options
+            if ( of_type == o.value ) {
+              // if length is allowed for selected type
+              if(o.length)
+              {
+                // set the values in state
+                state.is_tlength = true;
+                state.min_val = o.min_val;
+                state.max_val = o.max_val;
+              } else {
+                // set the values in state
+                state.is_tlength = false;
+              }
+              return;
+            }
+          });
+        }
+        return state.is_tlength;
+      },
+    }, {
+      // Note: There are ambiguities in the PG catalogs and docs between
+      // precision and scale. In the UI, we try to follow the docs as
+      // closely as possible, therefore we use Length/Precision and Scale
+      id: 'precision', label: gettext('Scale'), deps: ['type'],
+      type: 'text', disabled: false, cell: 'int',
+      depChange: (state, changeSource)=>{
+        if(_.isArray(changeSource) && changeSource[2] == 'type') {
+          return {...state
+            , value: null
+          };
+        }
+      },
+      editable: (state) => {
+        // We will store type from selected from combobox
+        var of_type = state.type;
+        if(obj.type_options) {
+          // iterating over all the types
+          _.each(obj.type_options, function(o) {
+            // if type from selected from combobox matches in options
+            if ( of_type == o.value ) {
+              // if precession is allowed for selected type
+              if(o.precision)
+              {
+                // set the values in state
+                state.is_precision = true;
+                state.min_val = o.min_val;
+                state.max_val = o.max_val;
+              } else {
+                // set the values in state
+                state.is_precision = false;
+              }
+            }
+          });
+        }
+        return state.is_precision;
+      },
+    }, {
+      id: 'collation', label: gettext('Collation'), type: 'text',
+      depChange: (state, changeSource)=>{
+        if(_.isArray(changeSource) && changeSource[2] == 'type') {
+          return {...state
+            , value: null
+          };
+        }
+      },
+      cell: ()=>({
+        cell: 'select', options: obj.fieldOptions.collations,
+        controlProps: {
+          allowClear: false,
+        }
+      }),
+      deps: ['type'],
+      editable: (state) => {
+        // We will store type from selected from combobox
+        var of_type = state.type;
+        var flag = false;
+        if(obj.type_options) {
+          // iterating over all the types
+          _.each(obj.type_options, function(o) {
+            // if type from selected from combobox matches in options
+            if ( of_type == o.value ) {
+              if(o.is_collatable) {
+                flag = true;
+                return;
+              }
+            }
+          });
+        }
+        return flag;
+      },
+    }];
+  }
+
+  validate(state, setError) {
+
+    let errmsg = null;
+
+    if (isEmptyString(state.member_name)) {
+      errmsg = gettext('Please specify the value for member name.');
+      setError('member_name', errmsg);
+      return true;
+    } else if(isEmptyString(state.type)) {
+      errmsg = gettext('Please specify the type.');
+      setError('type', errmsg);
+      return true;
+    }
+    if(state.is_tlength) {
+
+      if (state.tlength < state.min_val) {
+        errmsg = gettext('Length/Precision should not be less than %s.', state.min_val);
+      }
+      else if (state.tlength > state.max_val) {
+        errmsg = gettext('Length/Precision should not be greater than %s.', state.max_val);
+      }
+      if(_.isUndefined(errmsg) || errmsg == null)
+        errmsg = integerValidator('Length/Precision', state.tlength);
+      // If we have any error set then throw it to user
+      if(!_.isUndefined(errmsg) && errmsg != null) {
+        setError('tlength', errmsg);
+        return true;
+      }
+    }
+    if(state.is_precision) {
+      errmsg = integerValidator('Scale', state.precision);
+      if(!_.isUndefined(errmsg) && errmsg != null) {
+        setError('precision', errmsg);
+        return true;
+      }
+    }
+    if(_.isUndefined(errmsg) || errmsg == null) {
+      errmsg = null;
+      setError('member_name', errmsg);
+      setError('type', errmsg);
+      setError('tlength', errmsg);
+      setError('precision', errmsg);
+    }
+    return false;
+  }
+}
+
+class DataTypeSchema extends BaseUISchema {
+
+  constructor(fieldOptions = {}, initValues) {
+    super({
+      oid: undefined,
+      is_sys_type: false,
+      attnum: undefined,
+      member_name: undefined,
+      type: undefined,
+      tlength: null,
+      is_tlength: false,
+      precision: undefined,
+      is_precision: false,
+      min_val: undefined,
+      max_val: undefined,
+      attlen: undefined,
+      min_val_attlen: undefined,
+      max_val_attlen: undefined,
+      attprecision: null,
+      min_val_attprecision: undefined,
+      max_val_attprecision: undefined,
+      ...initValues
+    });
+    this.types = fieldOptions.types;
+    this.type_options = [];
+  }
+
+  get idAttribute() {
+    return 'oid';
+  }
+
+  get baseFields() {
+    var dataTypeObj = this;
+    return [{
+      id: 'type',
+      label: gettext('Data Type'),
+      group: gettext('Definition'),
+      mode: ['edit', 'create','properties'],
+      disabled: false,
+      readonly: function (state) {
+        return !dataTypeObj.isNew(state);
+      },
+      node: 'type',
+      cache_node: 'domain',
+      editable: true,
+      deps: ['typtype'],
+      type: (state) => {
+        return {
+          type: 'select',
+          options: dataTypeObj.types,
+          optionsLoaded: (options) => { dataTypeObj.types = options; },
+          controlProps: {
+            allowClear: false,
+            filter: (options) => {
+              var data_types = [];
+              options.forEach((option) => {
+                if (!(option.value.includes('[]'))) {
+                  data_types.push(option);
+                }
+              });
+              state.type_options = data_types;
+              return data_types;
+            }
+          }
+        };
+      }
+    },{
+      id: 'maxsize',
+      group: gettext('Definition'),
+      label: gettext('Size'),
+      type: 'int',
+      deps: ['typtype'],
+      cell: 'int',
+      mode: ['create', 'edit','properties'],
+      readonly: function (state) {
+        return !dataTypeObj.isNew(state);
+      },
+      visible: function (state) {
+        return state.typtype === 'V';
+      }
+    },{
+    // Note: There are ambiguities in the PG catalogs and docs between
+    // precision and scale. In the UI, we try to follow the docs as
+    // closely as possible, therefore we use Length/Precision and Scale
+      id: 'tlength',
+      group: gettext('Data Type'),
+      label: gettext('Length/Precision'),
+      mode: ['edit', 'create','properties'],
+      deps: ['type'],
+      type: 'text',
+      cell: 'int',
+      readonly: function (state) {
+        return !dataTypeObj.isNew(state);
+      },
+      visible: function (state) {
+        return state.typtype === 'N';
+      },
+      disabled: function(state) {
+
+        var of_type = state.type,
+          flag = true;
+        if (state.type_options) {
+          _.each(state.type_options, function (o) {
+            if (of_type == o.value) {
+              if (o.length) {
+                state.min_val_attlen = o.min_val;
+                state.max_val_attlen = o.max_val;
+                flag = false;
+              }
+            }
+          });
+        }
+        flag && setTimeout(function () {
+          if (state.attlen) {
+            state.attlen = null;
+          }
+        }, 10);
+        return flag;
+      },
+      editable: function(state) {
+        // We will store type from selected from combobox
+        var of_type = state.type;
+        if (state.type_options) {
+          // iterating over all the types
+          _.each(state.type_options, function (o) {
+          // if type from selected from combobox matches in options
+            if (of_type == o.value) {
+              // if length is allowed for selected type
+              if (o.length) {
+                // set the values in state
+                state.is_tlength = true;
+                state.min_val = o.min_val;
+                state.max_val = o.max_val;
+              } else {
+                // set the values in staet
+                state.is_tlength = false;
+              }
+            }
+          });
+        }
+        return state.is_tlength;
+      }
+    },{
+      // Note: There are ambiguities in the PG catalogs and docs between
+      // precision and scale. In the UI, we try to follow the docs as
+      // closely as possible, therefore we use Length/Precision and Scale
+      id: 'precision',
+      group: gettext('Data Type'),
+      label: gettext('Scale'),
+      mode: ['edit', 'create','properties'],
+      deps: ['type'],
+      type: 'text',
+      readonly: function (state) {
+        return !dataTypeObj.isNew(state);
+      },
+      cell: 'int',
+      visible: function (state) {
+        return state.typtype === 'N';
+      },
+      disabled: function(state) {
+        var of_type = state.type,
+          flag = true;
+        _.each(state.type_options, function(o) {
+          if ( of_type == o.value ) {
+            if(o.precision) {
+              state.min_val_attprecision  = 0;
+              state.max_val_attprecision = o.max_val;
+              flag = false;
+            }
+          }
+        });
+
+        flag && setTimeout(function() {
+          if(state.attprecision) {
+            state.attprecision = null;
+          }
+        },10);
+        return flag;
+      },
+      editable: function(state) {
+        // We will store type from selected from combobox
+        var of_type = state.type;
+        if(state.type_options) {
+          // iterating over all the types
+          _.each(state.type_options, function(o) {
+            // if type from selected from combobox matches in options
+            if ( of_type == o.value ) {
+              // if precession is allowed for selected type
+              if(o.precision)
+              {
+                // set the values in model
+                state.is_precision = true;
+                state.min_val = o.min_val;
+                state.max_val = o.max_val;
+              } else {
+                // set the values in model
+                state.is_precision = false;
+              }
+            }
+          });
+        }
+        return state.is_precision;
+      },
+    }];
+  }
+}
+
+function inSchema(node_info) {
+  if(node_info &&  'catalog' in node_info)
+  {
+    return true;
+  }
+  return false;
+}
+
+export default class TypeSchema extends BaseUISchema {
+  constructor(getPrivilegeRoleSchema, getCompositeSchema, getRangeSchema, getExternalSchema, getDataTypeSchema, fieldOptions = {}, initValues) {
+    super({
+      name: null,
+      oid: undefined,
+      is_sys_type: false,
+      typtype: undefined,
+      typeowner: undefined,
+      schema: undefined,
+      ...initValues
+    });
+    this.fieldOptions = {
+      roles: [],
+      schemas: [],
+      server_info: [],
+      node_info: [],
+      ...fieldOptions
+    };
+    this.getPrivilegeRoleSchema = getPrivilegeRoleSchema;
+    this.getCompositeSchema = getCompositeSchema;
+    this.getRangeSchema = getRangeSchema;
+    this.getExternalSchema = getExternalSchema;
+    this.getDataTypeSchema = getDataTypeSchema;
+  }
+
+  schemaCheck(state) {
+    if(this.fieldOptions.node_info && 'schema' in this.fieldOptions.node_info)
+    {
+      if(!state)
+        return true;
+      if (this.isNew(state)) {
+        return false;
+      } else {
+        return state && state.typtype === 'p';
+      }
+    }
+    return true;
+  }
+
+  get idAttribute() {
+    return 'oid';
+  }
+
+  get baseFields() {
+    var obj = this;
+    return [{
+      id: 'name', label: gettext('Name'), cell: 'string',
+      type: 'text', mode: ['properties', 'create', 'edit'],
+      noEmpty: true,
+      disabled: (state) => obj.schemaCheck(state),
+    },{
+      id: 'oid', label: gettext('OID'), cell: 'string',
+      type: 'text' , mode: ['properties'],
+    },{
+      id: 'typeowner', label: gettext('Owner'), cell: 'string',
+      mode: ['properties', 'create', 'edit'], noEmpty: true,
+      type: 'select', options: this.fieldOptions.roles,
+      controlProps: { allowClear: false },
+      disabled: () => inSchema(obj.node_info),
+    },{
+      id: 'schema', label: gettext('Schema'), cell: 'string',
+      mode: ['create', 'edit'], noEmpty: true,
+      disabled: (state) => obj.schemaCheck(state),
+      type: (state) => {
+        return {
+          type: 'select',
+          options: obj.fieldOptions.schemas,
+          optionsLoaded: (options) => { obj.fieldOptions.schemas = options; },
+          controlProps: {
+            allowClear: true,
+            filter: (options) => {
+              let res = [];
+              if (state && obj.isNew(state)) {
+                options.forEach((option) => {
+                  // If schema name start with pg_* then we need to exclude them
+                  if(option && option.label.match(/^pg_/)) {
+                    return;
+                  }
+                  res.push({ label: option.label, value: option.value });
+                });
+              } else {
+                res = options;
+              }
+              return res;
+            }
+          }
+        };
+      }
+    },
+    {
+      id: 'typtype', label: gettext('Type'),
+      mode: ['create','edit'], group: gettext('Definition'),
+      type: 'select',
+      disabled: () => inSchema(obj.node_info),
+      readonly: function (state) {
+        return !obj.isNew(state);
+      },
+      controlProps: { allowClear: false },
+      options: function() {
+        var typetype = [
+          {label: gettext('Composite'), value: 'c'},
+          {label: gettext('Enumeration'), value: 'e'},
+          {label: gettext('External'), value: 'b'},
+          {label: gettext('Range'), value: 'r'},
+          {label: gettext('Shell'), value: 'p'},
+        ];
+        if (obj.fieldOptions.server_info.server_type === 'ppas' &&
+        obj.fieldOptions.server_info.version >= 90500){
+          typetype.push(
+            {label: gettext('Nested Table'), value: 'N'},
+            {label: gettext('Varying Array'), value: 'V'}
+          );
+        }
+        return typetype;
+      },
+    },
+    {
+      id: 'composite', label: gettext('Composite Type'),
+      editable: true, type: 'collection',
+      group: gettext('Definition'), mode: ['edit', 'create'],
+      uniqueCol : ['member_name'],
+      canAdd: true,  canEdit: false, canDelete: true,
+      disabled: () => inSchema(obj.node_info),
+      schema: obj.getCompositeSchema(),
+      deps: ['typtype'],
+      visible: (state) => {
+        return state.typtype === 'c';
+      },
+    },
+    {
+      id: 'enum', label: gettext('Enumeration type'),
+      schema: new EnumerationSchema(),
+      editable: true,
+      type: 'collection',
+      group: gettext('Definition'), mode: ['edit', 'create'],
+      canAdd: true,  canEdit: false,
+      canDelete: function(state) {
+        // We will disable it if it's in 'edit' mode
+        return !obj.isNew(state);
+      },
+      disabled: () => inSchema(obj.node_info),
+      deps: ['typtype'],
+      uniqueCol : ['label'],
+      visible: function(state) {
+        return state.typtype === 'e';
+      },
+    }, {
+      type: 'nested-fieldset',
+      group: gettext('Definition'),
+      label: '',
+      deps: ['typtype'],
+      mode: ['edit', 'create', 'properties'],
+      visible: function(state) {
+        return state.typtype === 'N' || state.typtype === 'V';
+      },
+      schema: obj.getDataTypeSchema()
+    }, {
+      // We will disable range type control in edit mode
+      type: 'nested-fieldset',
+      group: gettext('Definition'),
+      label: '',
+      mode: ['edit', 'create'],
+      visible: (state) => {
+        return state.typtype && state.typtype === 'r';
+      },
+      deps: ['typtype'],
+      schema: obj.getRangeSchema(),
+    }, {
+      type: 'nested-tab',
+      group: gettext('Definition'),
+      label: gettext('External Type'), deps: ['typtype'],
+      mode: ['create', 'edit'], tabPanelExtraClasses:'inline-tab-panel-padded',
+      visible: function(state) {
+        return state.typtype === 'b';
+      },
+      schema: obj.getExternalSchema(),
+    },
+    {
+      id: 'alias', label: gettext('Alias'), cell: 'string',
+      type: 'text', mode: ['properties'],
+      disabled: () => inSchema(obj.node_info),
+    },
+    {
+      id: 'member_list', label: gettext('Members'), cell: 'string',
+      type: 'text', mode: ['properties'], group: gettext('Definition'),
+      disabled: () => inSchema(obj.node_info),
+      visible: function(state) {
+        if(state.typtype === 'c') {
+          return true;
+        }
+        return false;
+      },
+    },{
+      id: 'enum_list', label: gettext('Labels'), cell: 'string',
+      type: 'text', mode: ['properties'], group: gettext('Definition'),
+      disabled: () => inSchema(obj.node_info),
+      visible: function(state) {
+        if(state.typtype === 'e') {
+          return true;
+        }
+        return false;
+      },
+    },
+    {
+      id: 'typname', label: gettext('SubType'), cell: 'string',
+      type: 'text', mode: ['properties'], group: gettext('Definition'),
+      disabled: () => inSchema(obj.node_info),
+      visible: function(state) {
+        if(state.typtype === 'r') {
+          return true;
+        }
+        return false;
+      },
+    },
+    {
+      id: 'opcname', label: gettext('Subtype operator class'), cell: 'string',
+      type: 'text', mode: ['properties'], group: gettext('Definition'),
+      disabled: () => inSchema(obj.node_info),
+      visible: function(state) {
+        if(state.typtype === 'r') {
+          return true;
+        }
+        return false;
+      },
+    },
+    {
+      id: 'collname', label: gettext('Collation'), cell: 'string',
+      type: 'text', mode: ['properties'], group: gettext('Definition'),
+      disabled: () => inSchema(obj.node_info),
+      visible: function(state) {
+        if(state.typtype === 'r') {
+          return true;
+        }
+        return false;
+      },
+    },
+    {
+      id: 'rngcanonical', label: gettext('Canonical function'), cell: 'string',
+      type: 'text', mode: ['properties'], group: gettext('Definition'),
+      disabled: () => inSchema(obj.node_info),
+      visible: function(state) {
+        if(state.typtype === 'r') {
+          return true;
+        }
+        return false;
+      },
+    },
+    {
+      id: 'rngsubdiff', label: gettext('Subtype diff function'), cell: 'string',
+      type: 'text', mode: ['properties'], group: gettext('Definition'),
+      disabled: () => inSchema(obj.node_info),
+      visible: function(state) {
+        if(state.typtype === 'r') {
+          return true;
+        }
+        return false;
+      },
+    },
+    {
+      id: 'typinput', label: gettext('Input function'), cell: 'string',
+      type: 'text', mode: ['properties'], group: gettext('Definition'),
+      disabled: () => inSchema(obj.node_info),
+      visible: function(state) {
+        if(state.typtype === 'b') {
+          return true;
+        }
+        return false;
+      },
+    },
+    {
+      id: 'typoutput', label: gettext('Output function'), cell: 'string',
+      type: 'text', mode: ['properties'], group: gettext('Definition'),
+      disabled: () => inSchema(obj.node_info),
+      visible: function(state) {
+        if(state.typtype === 'b') {
+          return true;
+        }
+        return false;
+      },
+    },
+    {
+      id: 'type_acl', label: gettext('Privileges'), cell: 'string',
+      type: 'text', mode: ['properties'], group: gettext('Security'),
+      disabled: () => inSchema(obj.node_info),
+    },
+    {
+      id: 'is_sys_type', label: gettext('System type?'), cell: 'switch',
+      type: 'switch', mode: ['properties'],
+      disabled: () => inSchema(obj.node_info),
+    },
+    {
+      id: 'description', label: gettext('Comment'), cell: 'string',
+      type: 'multiline', mode: ['properties', 'create', 'edit'],
+      disabled: () => inSchema(obj.node_info),
+    },
+    {
+      id: 'typacl', label: gettext('Privileges'), type: 'collection',
+      group: gettext('Security'),
+      schema: this.getPrivilegeRoleSchema(['U']),
+      mode: ['edit', 'create'], canDelete: true,
+      uniqueCol : ['grantee'], deps: ['typtype'],
+      canAdd: function(state) {
+        // Do not allow to add when shell type is selected
+        // Clear acl & security label collections as well
+        if (state.typtype === 'p') {
+          var acl = state.typacl;
+          if(acl && acl.length > 0)
+            acl.reset();
+        }
+        return (state.typtype !== 'p');
+      },
+    },
+    {
+      id: 'seclabels', label: gettext('Security labels'),
+      schema: new SecLabelSchema(),
+      editable: false, type: 'collection',
+      group: gettext('Security'), mode: ['edit', 'create'],
+      min_version: 90100, canEdit: false, canDelete: true,
+      uniqueCol : ['provider'], deps: ['typtype'],
+      canAdd: function(state) {
+        // Do not allow to add when shell type is selected
+        // Clear acl & security label collections as well
+        if (state.typtype === 'p') {
+          var secLabs = state.seclabels;
+          if(secLabs && secLabs.length > 0)
+            secLabs.reset();
+        }
+        return (state.typtype !== 'p');
+      },
+    }];
+  }
+}
+
+export {
+  CompositeSchema,
+  EnumerationSchema,
+  ExternalSchema,
+  RangeSchema,
+  getCompositeSchema,
+  getRangeSchema,
+  getExternalSchema,
+  getDataTypeSchema
+};
\ No newline at end of file
diff --git a/web/pgadmin/static/js/SchemaView/FieldSetView.jsx b/web/pgadmin/static/js/SchemaView/FieldSetView.jsx
index 611f6e5f8..5953c397d 100644
--- a/web/pgadmin/static/js/SchemaView/FieldSetView.jsx
+++ b/web/pgadmin/static/js/SchemaView/FieldSetView.jsx
@@ -20,7 +20,7 @@ import { getFieldMetaData } from './FormView';
 import FieldSet from '../components/FieldSet';
 
 export default function FieldSetView({
-  value, formErr, schema={}, viewHelperProps, accessPath, dataDispatch, controlClassName, isDataGridForm=false, label}) {
+  value, formErr, schema={}, viewHelperProps, accessPath, dataDispatch, controlClassName, isDataGridForm=false, label, visible}) {
   const depListener = useContext(DepListenerContext);
 
   useEffect(()=>{
@@ -91,6 +91,10 @@ export default function FieldSetView({
     }
   });
 
+  if(!visible) {
+    return <></>;
+  }
+
   return (
     <FieldSet title={label} className={controlClassName}>
       {viewFields}
@@ -108,4 +112,7 @@ FieldSetView.propTypes = {
   dataDispatch: PropTypes.func,
   controlClassName: CustomPropTypes.className,
   label: PropTypes.string,
+  visible: PropTypes.oneOfType([
+    PropTypes.bool, PropTypes.func,
+  ]),
 };
diff --git a/web/pgadmin/static/js/SchemaView/FormView.jsx b/web/pgadmin/static/js/SchemaView/FormView.jsx
index 2b6e174b6..b3d51ef08 100644
--- a/web/pgadmin/static/js/SchemaView/FormView.jsx
+++ b/web/pgadmin/static/js/SchemaView/FormView.jsx
@@ -122,7 +122,7 @@ export function getFieldMetaData(field, schema, value, viewHelperProps) {
 /* The first component of schema view form */
 export default function FormView({
   value, formErr, schema={}, viewHelperProps, isNested=false, accessPath, dataDispatch, hasSQLTab,
-  getSQLValue, onTabChange, firstEleRef, className, isDataGridForm=false}) {
+  getSQLValue, onTabChange, firstEleRef, className, isDataGridForm=false, visible}) {
   let defaultTab = 'General';
   let tabs = {};
   let tabsClassname = {};
@@ -190,7 +190,8 @@ export default function FormView({
         }
         tabs[group].push(
           <FormView key={`nested${tabs[group].length}`} value={value} viewHelperProps={viewHelperProps} formErr={formErr}
-            schema={field.schema} accessPath={accessPath} dataDispatch={dataDispatch} isNested={true} isDataGridForm={isDataGridForm} {...field}/>
+            schema={field.schema} accessPath={accessPath} dataDispatch={dataDispatch} isNested={true} isDataGridForm={isDataGridForm} 
+            {...field} visible={visible}/>
         );
       } else if(field.type === 'nested-fieldset') {
         /* Pass on the top schema */
@@ -203,7 +204,7 @@ export default function FormView({
           <FieldSetView key={`nested${tabs[group].length}`} value={value} viewHelperProps={viewHelperProps} formErr={formErr}
             schema={field.schema} accessPath={accessPath} dataDispatch={dataDispatch} isNested={true} isDataGridForm={isDataGridForm}
             controlClassName={classes.controlRow}
-            {...field} />
+            {...field} visible={visible}/>
         );
       } else if(field.type === 'collection') {
         /* If its a collection, let data grid view handle it */
@@ -305,6 +306,11 @@ export default function FormView({
     onTabChange && onTabChange(tabValue, Object.keys(tabs)[tabValue], sqlTabActive);
   }, [tabValue]);
 
+  /* check whether form is kept hidden by visible prop */
+  if(!_.isUndefined(visible) && !visible) {
+    return <></>;
+  }
+
   return (
     <>
       <Box height="100%" display="flex" flexDirection="column" className={className} ref={formRef}>
@@ -343,6 +349,9 @@ FormView.propTypes = {
   viewHelperProps: PropTypes.object,
   isNested: PropTypes.bool,
   isDataGridForm: PropTypes.bool,
+  visible: PropTypes.oneOfType([
+    PropTypes.bool, PropTypes.func,
+  ]),
   accessPath: PropTypes.array.isRequired,
   dataDispatch: PropTypes.func,
   hasSQLTab: PropTypes.bool,
diff --git a/web/regression/javascript/fake_messages.js b/web/regression/javascript/fake_messages.js
index f8888a838..5fbcdae8b 100644
--- a/web/regression/javascript/fake_messages.js
+++ b/web/regression/javascript/fake_messages.js
@@ -15,6 +15,7 @@ define('pgadmin.browser.messages',['sources/pgadmin'], function(pgAdmin) {
 
   pgBrowser.messages = {
     'CANNOT_BE_EMPTY': '\'%s\' cannot be empty.',
+    'MUST_BE_INT': '\'%s\' must be an integer.'
   };
   return pgBrowser;
 });
diff --git a/web/regression/javascript/schema_ui_files/type.ui.spec.js b/web/regression/javascript/schema_ui_files/type.ui.spec.js
new file mode 100644
index 000000000..88c42ca81
--- /dev/null
+++ b/web/regression/javascript/schema_ui_files/type.ui.spec.js
@@ -0,0 +1,457 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2021, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import jasmineEnzyme from 'jasmine-enzyme';
+import React from 'react';
+import '../helper/enzyme.helper';
+import pgAdmin from 'sources/pgadmin';
+import {messages} from '../fake_messages';
+import { createMount } from '@material-ui/core/test-utils';
+import SchemaView from '../../../pgadmin/static/js/SchemaView';
+import * as nodeAjax from '../../../pgadmin/browser/static/js/node_ajax';
+import gettext from 'sources/gettext';
+import { integerValidator } from 'sources/validators';
+import { getNodePrivilegeRoleSchema } from '../../../pgadmin/browser/server_groups/servers/static/js/privilege.ui';
+
+import TypeSchema, { EnumerationSchema, getCompositeSchema, getExternalSchema, getRangeSchema, getDataTypeSchema } from '../../../pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.ui';
+
+describe('TypeSchema', ()=>{
+
+  let mount;
+  let getInitData = ()=>Promise.resolve({});
+
+  /* Use createMount so that material ui components gets the required context */
+  /* https://material-ui.com/guides/testing/#api */
+  beforeAll(()=>{
+    mount = createMount();
+  });
+
+  afterAll(() => {
+    mount.cleanUp();
+  });
+
+  beforeEach(()=>{
+    jasmineEnzyme();
+    /* messages used by validators */
+    pgAdmin.Browser = pgAdmin.Browser || {};
+    pgAdmin.Browser.messages = pgAdmin.Browser.messages || messages;
+    pgAdmin.Browser.utils = pgAdmin.Browser.utils || {};
+    pgAdmin.Browser.utils.support_ssh_tunnel = true;
+  });
+
+  describe('composite schema describe', () => {
+
+    let compositeCollObj = getCompositeSchema({}, {server: {user: {name: 'postgres'}}}, {});
+    let types = [{ label: '', value: ''}, { label: 'lb1', value: 'numeric[]', length: true, min_val: 10, max_val: 100, precision: true, is_collatable: true}];
+    let collations = [{ label: '', value: ''}, { label: 'lb1', value: 'numeric[]'}];
+
+    it('composite collection', ()=>{
+
+      spyOn(nodeAjax, 'getNodeAjaxOptions').and.returnValue([]);
+      spyOn(compositeCollObj.fieldOptions, 'types').and.returnValue(types);
+      spyOn(compositeCollObj.fieldOptions, 'collations').and.returnValue(collations);
+
+      spyOn(compositeCollObj, 'type_options').and.returnValue(compositeCollObj.fieldOptions.types());
+
+      mount(<SchemaView
+        formType='dialog'
+        schema={compositeCollObj}
+        viewHelperProps={{
+          mode: 'create',
+        }}
+        onSave={()=>{}}
+        onClose={()=>{}}
+        onHelp={()=>{}}
+        onEdit={()=>{}}
+        onDataChange={()=>{}}
+        confirmOnCloseReset={false}
+        hasSQL={false}
+        disableSqlHelp={false}
+      />);
+
+      mount(<SchemaView
+        formType='dialog'
+        schema={compositeCollObj}
+        viewHelperProps={{
+          mode: 'edit',
+        }}
+        onSave={()=>{}}
+        onClose={()=>{}}
+        getInitData={getInitData}
+        onHelp={()=>{}}
+        onEdit={()=>{}}
+        onDataChange={()=>{}}
+        confirmOnCloseReset={false}
+        hasSQL={false}
+        disableSqlHelp={false}
+      />);
+    });
+
+    it('composite validate', () => {
+      let state = { typtype: 'b' }; //validating for ExternalSchema which is distinguish as r
+      let setError = jasmine.createSpy('setError');
+
+      compositeCollObj.validate(state, setError);
+      expect(setError).toHaveBeenCalledWith('member_name', 'Please specify the value for member name.');
+
+      state.member_name = 'demo_member';
+      compositeCollObj.validate(state, setError);
+      expect(setError).toHaveBeenCalledWith('type', 'Please specify the type.');
+
+      state.type = 'char';
+      state.min_val = 10;
+      state.max_val = 100;
+      state.is_tlength = true;
+      state.tlength = 9;
+      compositeCollObj.validate(state, setError);
+      expect(setError).toHaveBeenCalledWith('tlength', gettext('Length/Precision should not be less than %s.', state.min_val));
+
+      state.tlength = 200;
+      compositeCollObj.validate(state, setError);
+      expect(setError).toHaveBeenCalledWith('tlength', gettext('Length/Precision should not be greater than %s.', state.max_val));
+
+      state.tlength = 'ert';
+      compositeCollObj.validate(state, setError);
+      expect(setError).toHaveBeenCalledWith('tlength', integerValidator('Length/Precision', state.tlength));
+
+      state.tlength = 90;
+      state.is_precision = true;
+      state.precision = 'ert';
+      compositeCollObj.validate(state, setError);
+      expect(setError).toHaveBeenCalledWith('precision', integerValidator('Scale', state.precision));
+
+      state.precision = 9;
+      compositeCollObj.validate(state, setError);
+      expect(setError).toHaveBeenCalled();
+    });
+
+    it('tlength editable', ()=>{
+      compositeCollObj.type_options = types;
+      let editable = _.find(compositeCollObj.fields, (f)=>f.id=='tlength').editable;
+      let status = editable({type: 'numeric[]'});
+      expect(status).toBe(true);
+    });
+
+    it('precision editable', ()=>{
+      compositeCollObj.type_options = types;
+      let editable = _.find(compositeCollObj.fields, (f)=>f.id=='precision').editable;
+      let status = editable({type: 'numeric[]'});
+      expect(status).toBe(true);
+    });
+
+    it('collation editable', ()=>{
+      compositeCollObj.type_options = types;
+      let editable = _.find(compositeCollObj.fields, (f)=>f.id=='collation').editable;
+      let status = editable({type: 'numeric[]'});
+      expect(status).toBe(true);
+    });
+
+    it('setTypeOptions', ()=>{
+      compositeCollObj.setTypeOptions(types);
+    });
+  });
+
+  describe('enumeration schema describe', () => {
+
+    it('enumeration collection', ()=>{
+
+      let enumerationCollObj = new EnumerationSchema(
+        ()=>[],
+        ()=>[]
+      );
+
+      mount(<SchemaView
+        formType='dialog'
+        schema={enumerationCollObj}
+        viewHelperProps={{
+          mode: 'create',
+        }}
+        onSave={()=>{}}
+        onClose={()=>{}}
+        onHelp={()=>{}}
+        onEdit={()=>{}}
+        onDataChange={()=>{}}
+        confirmOnCloseReset={false}
+        hasSQL={false}
+        disableSqlHelp={false}
+      />);
+
+      mount(<SchemaView
+        formType='dialog'
+        schema={enumerationCollObj}
+        viewHelperProps={{
+          mode: 'edit',
+        }}
+        onSave={()=>{}}
+        getInitData={getInitData}
+        onClose={()=>{}}
+        onHelp={()=>{}}
+        onEdit={()=>{}}
+        onDataChange={()=>{}}
+        confirmOnCloseReset={false}
+        hasSQL={false}
+        disableSqlHelp={false}
+      />);
+    });
+  });
+
+  describe('external schema describe', () => {
+
+    let externalCollObj = getExternalSchema({}, {server: {user: {name: 'postgres'}}}, {});
+
+    it('external collection', ()=>{
+
+      spyOn(nodeAjax, 'getNodeAjaxOptions').and.returnValue([]);
+      spyOn(externalCollObj.fieldOptions, 'externalFunctionsList').and.returnValue([{ label: '', value: ''}, { label: 'lb1', cbtype: 'typmodin', value: 'val1'}, { label: 'lb2', cbtype: 'all', value: 'val2'}]);
+      spyOn(externalCollObj.fieldOptions, 'types').and.returnValue([{ label: '', value: ''}]);
+
+      mount(<SchemaView
+        formType='dialog'
+        schema={externalCollObj}
+        viewHelperProps={{
+          mode: 'create',
+        }}
+        onSave={()=>{}}
+        onClose={()=>{}}
+        onHelp={()=>{}}
+        onEdit={()=>{}}
+        onDataChange={()=>{}}
+        confirmOnCloseReset={false}
+        hasSQL={false}
+        disableSqlHelp={false}
+      />);
+
+      mount(<SchemaView
+        formType='dialog'
+        schema={externalCollObj}
+        viewHelperProps={{
+          mode: 'edit',
+        }}
+        onSave={()=>{}}
+        onClose={()=>{}}
+        getInitData={getInitData}
+        onHelp={()=>{}}
+        onEdit={()=>{}}
+        onDataChange={()=>{}}
+        confirmOnCloseReset={false}
+        hasSQL={false}
+        disableSqlHelp={false}
+      />);
+    });
+
+    it('external validate', () => {
+      let state = { typtype: 'b' }; //validating for ExternalSchema which is distinguish as r
+      let setError = jasmine.createSpy('setError');
+
+      externalCollObj.validate(state, setError);
+      expect(setError).toHaveBeenCalledWith('typinput', 'Input function cannot be empty');
+
+      state.typinput = 'demo_input';
+      externalCollObj.validate(state, setError);
+      expect(setError).toHaveBeenCalledWith('typoutput', 'Output function cannot be empty');
+    });
+  });
+
+  describe('range schema describe', () => {
+
+    let rangeCollObj = getRangeSchema({}, {server: {user: {name: 'postgres'}}}, {});
+
+    it('range collection', ()=>{
+
+      spyOn(nodeAjax, 'getNodeAjaxOptions').and.returnValue([]);
+      spyOn(rangeCollObj.fieldOptions, 'getSubOpClass').and.returnValue([{ label: '', value: ''}, { label: 'lb1', value: 'val1'}]);
+      spyOn(rangeCollObj.fieldOptions, 'getCanonicalFunctions').and.returnValue([{ label: '', value: ''}, { label: 'lb1', value: 'val1'}]);
+      spyOn(rangeCollObj.fieldOptions, 'getSubDiffFunctions').and.returnValue([{ label: '', value: ''}, { label: 'lb1', value: 'val1'}]);
+      spyOn(rangeCollObj.fieldOptions, 'typnameList').and.returnValue([{ label: '', value: ''}, { label: 'lb1', value: 'val1'}]);
+      spyOn(rangeCollObj.fieldOptions, 'collationsList').and.returnValue([{ label: '', value: ''}, { label: 'lb1', value: 'val1'}]);
+
+      mount(<SchemaView
+        formType='dialog'
+        schema={rangeCollObj}
+        viewHelperProps={{
+          mode: 'create',
+        }}
+        onSave={()=>{}}
+        onClose={()=>{}}
+        onHelp={()=>{}}
+        onEdit={()=>{}}
+        onDataChange={()=>{}}
+        confirmOnCloseReset={false}
+        hasSQL={false}
+        disableSqlHelp={false}
+      />);
+
+      mount(<SchemaView
+        formType='dialog'
+        schema={rangeCollObj}
+        viewHelperProps={{
+          mode: 'edit',
+        }}
+        onSave={()=>{}}
+        onClose={()=>{}}
+        getInitData={getInitData}
+        onHelp={()=>{}}
+        onEdit={()=>{}}
+        onDataChange={()=>{}}
+        confirmOnCloseReset={false}
+        hasSQL={false}
+        disableSqlHelp={false}
+      />);
+    });
+
+    it('range validate', () => {
+      let state = { typtype: 'r' }; //validating for RangeSchema which is distinguish as r
+      let setError = jasmine.createSpy('setError');
+
+      rangeCollObj.validate(state, setError);
+      expect(setError).toHaveBeenCalledWith('typname', 'Subtype cannot be empty');
+    });
+  });
+
+  describe('data type schema describe', () => {
+
+    let dataTypeObj = getDataTypeSchema({}, {server: {user: {name: 'postgres'}}}, {});
+    let types = [{ label: '', value: ''}, { label: 'lb1', value: 'numeric', length: true, min_val: 10, max_val: 100, precision: true}];
+
+    it('data type collection', ()=>{
+
+      spyOn(nodeAjax, 'getNodeAjaxOptions').and.returnValue([]);
+
+      mount(<SchemaView
+        formType='dialog'
+        schema={dataTypeObj}
+        viewHelperProps={{
+          mode: 'create',
+        }}
+        onSave={()=>{}}
+        onClose={()=>{}}
+        onHelp={()=>{}}
+        onEdit={()=>{}}
+        onDataChange={()=>{}}
+        confirmOnCloseReset={false}
+        hasSQL={false}
+        disableSqlHelp={false}
+      />);
+
+      mount(<SchemaView
+        formType='dialog'
+        schema={dataTypeObj}
+        viewHelperProps={{
+          mode: 'edit',
+        }}
+        onSave={()=>{}}
+        getInitData={getInitData}
+        onClose={()=>{}}
+        onHelp={()=>{}}
+        onEdit={()=>{}}
+        onDataChange={()=>{}}
+        confirmOnCloseReset={false}
+        hasSQL={false}
+        disableSqlHelp={false}
+      />);
+    });
+
+    it('tlength editable', ()=>{
+      dataTypeObj.type_options = types;
+      let editable = _.find(dataTypeObj.fields, (f)=>f.id=='tlength').editable;
+      let status = editable({type: 'numeric', type_options: types});
+      expect(status).toBe(true);
+    });
+
+    it('tlength disabled', ()=>{
+      dataTypeObj.type_options = types;
+      let disabled = _.find(dataTypeObj.fields, (f)=>f.id=='tlength').disabled;
+      let status = disabled({type: 'numeric', type_options: types});
+      expect(status).toBe(false);
+    });
+
+    it('precision editable', ()=>{
+      dataTypeObj.type_options = types;
+      let editable = _.find(dataTypeObj.fields, (f)=>f.id=='precision').editable;
+      let status = editable({type: 'numeric', type_options: types});
+      expect(status).toBe(true);
+    });
+
+    it('precision disabled', ()=>{
+      dataTypeObj.type_options = types;
+      let disabled = _.find(dataTypeObj.fields, (f)=>f.id=='precision').disabled;
+      let status = disabled({type: 'numeric', type_options: types});
+      expect(status).toBe(false);
+    });
+  });
+
+  let typeSchemaObj = new TypeSchema(
+    (privileges)=>getNodePrivilegeRoleSchema({}, {server: {user: {name: 'postgres'}}}, {}, privileges),
+    ()=>getCompositeSchema({}, {server: {user: {name: 'postgres'}}}, {}),
+    ()=>getRangeSchema({}, {server: {user: {name: 'postgres'}}}, {}),
+    ()=>getExternalSchema({}, {server: {user: {name: 'postgres'}}}, {}),
+    ()=>getDataTypeSchema({}, {server: {user: {name: 'postgres'}}}, {}),
+    {
+      roles: ()=>[],
+      schemas: ()=>[{ label: 'pg_demo', value: 'pg_demo'}],
+      server_info: [],
+      node_info: {'schema': []}
+    },
+    {
+      typowner: 'postgres',
+      schema: 'public',
+      typtype: 'c'
+    }
+  );
+
+  it('create', ()=>{
+    mount(<SchemaView
+      formType='dialog'
+      schema={typeSchemaObj}
+      viewHelperProps={{
+        mode: 'create',
+      }}
+      onSave={()=>{}}
+      onClose={()=>{}}
+      onHelp={()=>{}}
+      onEdit={()=>{}}
+      onDataChange={()=>{}}
+      confirmOnCloseReset={false}
+      hasSQL={false}
+      disableSqlHelp={false}
+    />);
+  });
+
+  it('edit', ()=>{
+    mount(<SchemaView
+      formType='dialog'
+      schema={typeSchemaObj}
+      viewHelperProps={{
+        mode: 'edit',
+      }}
+      onSave={()=>{}}
+      getInitData={getInitData}
+      onClose={()=>{}}
+      onHelp={()=>{}}
+      onEdit={()=>{}}
+      onDataChange={()=>{}}
+      confirmOnCloseReset={false}
+      hasSQL={false}
+      disableSqlHelp={false}
+    />);
+  });
+
+  it('properties', ()=>{
+    mount(<SchemaView
+      formType='tab'
+      schema={typeSchemaObj}
+      getInitData={getInitData}
+      viewHelperProps={{
+        mode: 'properties',
+      }}
+      onHelp={()=>{}}
+      onEdit={()=>{}}
+    />);
+  });
+});
\ No newline at end of file
