diff --git a/lib/workers/repository/updates/__snapshots__/generate.spec.ts.snap b/lib/workers/repository/updates/__snapshots__/generate.spec.ts.snap
index 0cac1ab725db066de1212624d1b336732b87b498..2da948ad7a471cf3b8f0a2e44dcb1494f6fc24da 100644
--- a/lib/workers/repository/updates/__snapshots__/generate.spec.ts.snap
+++ b/lib/workers/repository/updates/__snapshots__/generate.spec.ts.snap
@@ -34,6 +34,18 @@ Object {
       "prTitle": "some-title",
       "prettyDepType": "dependency",
     },
+    Object {
+      "branchName": "some-branch",
+      "commitBodyTable": true,
+      "commitMessage": "",
+      "datasource": "npm",
+      "depName": "some-dep",
+      "displayFrom": "",
+      "displayTo": "1.0.0",
+      "newValue": "1.0.0",
+      "prTitle": "some-other-title",
+      "prettyDepType": "dependency",
+    },
     Object {
       "branchName": "some-branch",
       "commitMessage": "",
@@ -48,6 +60,80 @@ Object {
 }
 `;
 
+exports[`workers/repository/updates/generate generateBranchConfig() handles @types specially 1`] = `
+Object {
+  "automerge": false,
+  "blockedByPin": false,
+  "branchName": "some-branch",
+  "canBeUnpublished": false,
+  "commitBodyTable": true,
+  "commitMessage": "
+
+| datasource | package         | from  | to    |
+| ---------- | --------------- | ----- | ----- |
+| npm        | @types/some-dep | 0.5.7 | 0.5.8 |
+",
+  "datasource": "npm",
+  "depName": "some-dep",
+  "displayFrom": "",
+  "displayTo": "0.6.0",
+  "hasTypes": true,
+  "isRange": false,
+  "masterIssueApproval": false,
+  "masterIssuePrApproval": false,
+  "newValue": "0.6.0",
+  "prTitle": "some-title",
+  "prettyDepType": "dependency",
+  "recreateClosed": false,
+  "releaseTimestamp": undefined,
+  "reuseLockFiles": true,
+  "upgrades": Array [
+    Object {
+      "branchName": "some-branch",
+      "commitBodyTable": true,
+      "commitMessage": "",
+      "datasource": "npm",
+      "depName": "some-dep",
+      "displayFrom": "",
+      "displayTo": "0.6.0",
+      "isRange": false,
+      "newValue": "0.6.0",
+      "prTitle": "some-title",
+      "prettyDepType": "dependency",
+      "recreateClosed": false,
+    },
+    Object {
+      "branchName": "some-branch",
+      "commitBodyTable": true,
+      "commitMessage": "",
+      "datasource": "npm",
+      "depName": "some-dep",
+      "displayFrom": "",
+      "displayTo": "1.0.0",
+      "isRange": false,
+      "newValue": "1.0.0",
+      "prTitle": "some-other-title",
+      "prettyDepType": "dependency",
+    },
+    Object {
+      "branchName": "some-branch",
+      "commitBodyTable": true,
+      "commitMessage": "",
+      "currentValue": "0.5.7",
+      "datasource": "npm",
+      "depName": "@types/some-dep",
+      "displayFrom": "0.5.7",
+      "displayTo": "",
+      "fromVersion": "0.5.7",
+      "isRange": false,
+      "prTitle": "some-title",
+      "prettyDepType": "dependency",
+      "toVersion": "0.5.8",
+    },
+  ],
+}
+`;
+
 exports[`workers/repository/updates/generate generateBranchConfig() handles upgrades 1`] = `"some-title ()"`;
 
 exports[`workers/repository/updates/generate generateBranchConfig() supports manual prTitle 1`] = `"upgrade some-dep"`;
diff --git a/lib/workers/repository/updates/generate.spec.ts b/lib/workers/repository/updates/generate.spec.ts
index da2a1e94281aaba623f58ab2d4b0ffa5dd082b85..394c94c748a5b07bddd10fe96b8bbd3540bd0a21 100644
--- a/lib/workers/repository/updates/generate.spec.ts
+++ b/lib/workers/repository/updates/generate.spec.ts
@@ -395,10 +395,22 @@ describe('workers/repository/updates/generate', () => {
           newValue: '0.6.0',
           group: {},
         },
+        {
+          commitBodyTable: true,
+          datasource: datasourceNpm.id,
+          depName: 'some-dep',
+          groupName: null,
+          branchName: 'some-branch',
+          prTitle: 'some-other-title',
+          lazyGrouping: true,
+          newValue: '1.0.0',
+          group: {},
+        },
       ];
       const res = generateBranchConfig(branch);
       expect(res.recreateClosed).toBe(false);
       expect(res.groupName).toBeUndefined();
+      expect(generateBranchConfig(branch)).toMatchSnapshot();
     });
     it('handles @types specially (reversed)', () => {
       const branch: BranchUpgradeConfig[] = [
@@ -411,6 +423,17 @@ describe('workers/repository/updates/generate', () => {
           newValue: '0.6.0',
           group: {},
         },
+        {
+          commitBodyTable: true,
+          datasource: datasourceNpm.id,
+          depName: 'some-dep',
+          groupName: null,
+          branchName: 'some-branch',
+          prTitle: 'some-other-title',
+          lazyGrouping: true,
+          newValue: '1.0.0',
+          group: {},
+        },
         {
           depName: '@types/some-dep',
           groupName: null,
diff --git a/lib/workers/repository/updates/generate.ts b/lib/workers/repository/updates/generate.ts
index 134141e67b8f9086bc580305e509bb66faaa4da5..4d4dc0874ddc49cf5f7815b0c8520a3c54ba5a12 100644
--- a/lib/workers/repository/updates/generate.ts
+++ b/lib/workers/repository/updates/generate.ts
@@ -8,23 +8,26 @@ import { sanitize } from '../../../util/sanitize';
 import * as template from '../../../util/template';
 import { BranchConfig, BranchUpgradeConfig } from '../../common';
 
-function ifTypesGroup(
-  depNames: string[],
-  hasGroupName: boolean,
-  branchUpgrades: any[]
-): boolean {
+function isTypesGroup(branchUpgrades: any[]): boolean {
   return (
-    depNames.length === 2 &&
-    !hasGroupName &&
-    ((branchUpgrades[0].depName &&
-      branchUpgrades[0].depName.startsWith('@types/') &&
-      branchUpgrades[0].depName.endsWith(branchUpgrades[1].depName)) ||
-      (branchUpgrades[1].depName &&
-        branchUpgrades[1].depName.startsWith('@types/') &&
-        branchUpgrades[1].depName.endsWith(branchUpgrades[0].depName)))
+    branchUpgrades.some(({ depName }) => depName?.startsWith('@types/')) &&
+    new Set(
+      branchUpgrades.map(({ depName }) => depName?.replace(/^@types\//, ''))
+    ).size === 1
   );
 }
 
+function sortTypesGroup(upgrades: BranchUpgradeConfig[]): void {
+  const isTypesUpgrade = ({ depName }: BranchUpgradeConfig): boolean =>
+    depName?.startsWith('@types/');
+  const regularUpgrades = upgrades.filter(
+    (upgrade) => !isTypesUpgrade(upgrade)
+  );
+  const typesUpgrades = upgrades.filter(isTypesUpgrade);
+  upgrades.splice(0, upgrades.length);
+  upgrades.push(...regularUpgrades, ...typesUpgrades);
+}
+
 function getTableValues(
   upgrade: BranchUpgradeConfig
 ): [string, string, string, string] | null {
@@ -97,6 +100,8 @@ export function generateBranchConfig(
     // eslint-disable-next-line no-param-reassign
     branchUpgrades[0].commitMessageExtra = `to v${toVersions[0]}`;
   }
+  const typesGroup =
+    depNames.length > 1 && !hasGroupName && isTypesGroup(branchUpgrades);
   logger.trace(`groupEligible: ${groupEligible}`);
   const useGroupSettings = hasGroupName && groupEligible;
   logger.trace(`useGroupSettings: ${useGroupSettings}`);
@@ -156,10 +161,8 @@ export function generateBranchConfig(
     delete upgrade.group;
     delete upgrade.lazyGrouping;
 
-    const isTypesGroup = ifTypesGroup(depNames, hasGroupName, branchUpgrades);
-
     // istanbul ignore else
-    if (toVersions.length > 1 && !isTypesGroup) {
+    if (toVersions.length > 1 && !typesGroup) {
       logger.trace({ toVersions });
       delete upgrade.commitMessageExtra;
       upgrade.recreateClosed = true;
@@ -264,25 +267,14 @@ export function generateBranchConfig(
       }
     }
   }
-  if (
-    depNames.length === 2 &&
-    !hasGroupName &&
-    config.upgrades[0].depName &&
-    config.upgrades[0].depName.startsWith('@types/') &&
-    config.upgrades[0].depName.endsWith(config.upgrades[1].depName)
-  ) {
-    logger.debug('Found @types - reversing upgrades to use depName in PR');
-    config.upgrades.reverse();
-    config.upgrades[0].recreateClosed = false;
-    config.hasTypes = true;
-  } else if (
-    depNames.length === 2 &&
-    !hasGroupName &&
-    config.upgrades[1].depName &&
-    config.upgrades[1].depName.startsWith('@types/') &&
-    config.upgrades[1].depName.endsWith(config.upgrades[0].depName)
-  ) {
-    // do nothing
+
+  if (typesGroup) {
+    if (config.upgrades[0].depName?.startsWith('@types/')) {
+      logger.debug('Found @types - reversing upgrades to use depName in PR');
+      sortTypesGroup(config.upgrades);
+      config.upgrades[0].recreateClosed = false;
+      config.hasTypes = true;
+    }
   } else {
     config.upgrades.sort((a, b) => {
       if (a.fileReplacePosition && b.fileReplacePosition) {