diff --git a/lib/permissions/minimally-encoded-thread-permissions.js b/lib/permissions/minimally-encoded-thread-permissions.js
--- a/lib/permissions/minimally-encoded-thread-permissions.js
+++ b/lib/permissions/minimally-encoded-thread-permissions.js
@@ -3,7 +3,6 @@
 import invariant from 'invariant';
 
 import { parseThreadPermissionString } from './prefixes.js';
-import { tHexEncodedRolePermission } from '../types/minimally-encoded-thread-permissions-types.js';
 import type {
   ThreadPermission,
   ThreadPermissionInfo,
@@ -11,6 +10,8 @@
   ThreadRolePermissionsBlob,
 } from '../types/thread-permission-types.js';
 import { entries, invertObjectToMap } from '../utils/objects.js';
+import type { TRegex } from '../utils/validation-utils.js';
+import { tRegex } from '../utils/validation-utils.js';
 
 // `baseRolePermissionEncoding` maps permission names to indices.
 // These indices represent the 6-bit basePermission part of the 10-bit role
@@ -76,6 +77,7 @@
   return bitmask.toString(16);
 };
 
+const tHexEncodedRolePermission: TRegex = tRegex(/^[0-9a-fA-F]{3,}$/);
 const threadPermissionsFromBitmaskHex = (
   permissionsBitmaskHex: string,
 ): ThreadPermissionsInfo => {
@@ -165,6 +167,7 @@
 const inverseFilterPrefixes: Map<bigint, string> =
   invertObjectToMap(filterPrefixes);
 
+const tHexEncodedPermissionsBitmask: TRegex = tRegex(/^[0-9a-fA-F]+$/);
 const decodeRolePermissionBitmask = (bitmask: string): string => {
   const bitmaskInt = BigInt(`0x${bitmask}`);
   const basePermission = (bitmaskInt >> BigInt(4)) & BigInt(63);
@@ -213,4 +216,6 @@
   decodeRolePermissionBitmask,
   threadRolePermissionsBlobToBitmaskArray,
   decodeThreadRolePermissionsBitmaskArray,
+  tHexEncodedRolePermission,
+  tHexEncodedPermissionsBitmask,
 };
diff --git a/lib/types/minimally-encoded-thread-permissions-types.js b/lib/types/minimally-encoded-thread-permissions-types.js
--- a/lib/types/minimally-encoded-thread-permissions-types.js
+++ b/lib/types/minimally-encoded-thread-permissions-types.js
@@ -4,9 +4,12 @@
 import type { TInterface } from 'tcomb';
 import t from 'tcomb';
 
-import { clientAvatarValidator } from './avatar-types.js';
-import { threadSubscriptionValidator } from './subscription-types.js';
-import { threadTypeValidator } from './thread-types-enum.js';
+import {
+  memberInfoValidator,
+  rawThreadInfoValidator,
+  roleInfoValidator,
+  threadCurrentUserInfoValidator,
+} from './thread-types.js';
 import type {
   MemberInfo,
   RawThreadInfo,
@@ -18,9 +21,10 @@
   permissionsToBitmaskHex,
   threadPermissionsFromBitmaskHex,
   threadRolePermissionsBlobToBitmaskArray,
+  tHexEncodedRolePermission,
+  tHexEncodedPermissionsBitmask,
 } from '../permissions/minimally-encoded-thread-permissions.js';
-import type { TRegex } from '../utils/validation-utils.js';
-import { tBool, tID, tRegex, tShape } from '../utils/validation-utils.js';
+import { tBool, tID, tShape } from '../utils/validation-utils.js';
 
 export type MinimallyEncodedRoleInfo = $ReadOnly<{
   ...RoleInfo,
@@ -28,13 +32,10 @@
   +permissions: $ReadOnlyArray<string>,
 }>;
 
-const tHexEncodedRolePermission: TRegex = tRegex(/^[0-9a-fA-F]{3,}$/);
 const minimallyEncodedRoleInfoValidator: TInterface<MinimallyEncodedRoleInfo> =
   tShape<MinimallyEncodedRoleInfo>({
+    ...roleInfoValidator.meta.props,
     minimallyEncoded: tBool(true),
-    id: tID,
-    name: t.String,
-    isDefault: t.Boolean,
     permissions: t.list(tHexEncodedRolePermission),
   });
 
@@ -64,14 +65,11 @@
   +permissions: string,
 }>;
 
-const tHexEncodedPermissionsBitmask: TRegex = tRegex(/^[0-9a-fA-F]+$/);
 const minimallyEncodedThreadCurrentUserInfoValidator: TInterface<MinimallyEncodedThreadCurrentUserInfo> =
   tShape<MinimallyEncodedThreadCurrentUserInfo>({
+    ...threadCurrentUserInfoValidator.meta.props,
     minimallyEncoded: tBool(true),
-    role: t.maybe(tID),
-    subscription: threadSubscriptionValidator,
     permissions: tHexEncodedPermissionsBitmask,
-    unread: t.maybe(t.Boolean),
   });
 
 const minimallyEncodeThreadCurrentUserInfo = (
@@ -102,11 +100,9 @@
 
 const minimallyEncodedMemberInfoValidator: TInterface<MinimallyEncodedMemberInfo> =
   tShape<MinimallyEncodedMemberInfo>({
+    ...memberInfoValidator.meta.props,
     minimallyEncoded: tBool(true),
-    id: t.String,
-    role: t.maybe(tID),
     permissions: tHexEncodedPermissionsBitmask,
-    isSender: t.Boolean,
   });
 
 const minimallyEncodeMemberInfo = (
@@ -139,23 +135,11 @@
 
 const minimallyEncodedRawThreadInfoValidator: TInterface<MinimallyEncodedRawThreadInfo> =
   tShape<MinimallyEncodedRawThreadInfo>({
+    ...rawThreadInfoValidator.meta.props,
     minimallyEncoded: tBool(true),
-    id: tID,
-    type: threadTypeValidator,
-    name: t.maybe(t.String),
-    avatar: t.maybe(clientAvatarValidator),
-    description: t.maybe(t.String),
-    color: t.String,
-    creationTime: t.Number,
-    parentThreadID: t.maybe(tID),
-    containingThreadID: t.maybe(tID),
-    community: t.maybe(tID),
     members: t.list(minimallyEncodedMemberInfoValidator),
     roles: t.dict(tID, minimallyEncodedRoleInfoValidator),
     currentUser: minimallyEncodedThreadCurrentUserInfoValidator,
-    sourceMessageID: t.maybe(tID),
-    repliesCount: t.Number,
-    pinnedCount: t.maybe(t.Number),
   });
 
 const minimallyEncodeRawThreadInfo = (
@@ -185,11 +169,9 @@
 };
 
 export {
-  tHexEncodedRolePermission,
   minimallyEncodedRoleInfoValidator,
   minimallyEncodeRoleInfo,
   decodeMinimallyEncodedRoleInfo,
-  tHexEncodedPermissionsBitmask,
   minimallyEncodedThreadCurrentUserInfoValidator,
   minimallyEncodeThreadCurrentUserInfo,
   decodeMinimallyEncodedThreadCurrentUserInfo,