diff --git a/substrate/frame/elections-phragmen/src/migrations_3_0_0.rs b/substrate/frame/elections-phragmen/src/migrations_3_0_0.rs
index 8adc4c1a69f7c41cef7303e04065253c5f69d5ab..8afc9ed66920b352bf8dbd99c686f3d6a45f0ffb 100644
--- a/substrate/frame/elections-phragmen/src/migrations_3_0_0.rs
+++ b/substrate/frame/elections-phragmen/src/migrations_3_0_0.rs
@@ -21,7 +21,6 @@ use codec::{Encode, Decode, FullCodec};
 use sp_std::prelude::*;
 use frame_support::{
 	RuntimeDebug, weights::Weight, Twox64Concat,
-	storage::types::{StorageMap, StorageValue},
 	traits::{GetPalletVersion, PalletVersion},
 };
 
@@ -51,38 +50,21 @@ pub trait V2ToV3 {
 	type Balance: 'static + FullCodec + Copy;
 }
 
-struct __Candidates;
-impl frame_support::traits::StorageInstance for __Candidates {
-	fn pallet_prefix() -> &'static str { "PhragmenElection" }
-	const STORAGE_PREFIX: &'static str = "Candidates";
-}
-
-#[allow(type_alias_bounds)]
-type Candidates<T: V2ToV3> = StorageValue<__Candidates, Vec<(T::AccountId, T::Balance)>>;
-
-struct __Members;
-impl frame_support::traits::StorageInstance for __Members {
-	fn pallet_prefix() -> &'static str { "PhragmenElection" }
-	const STORAGE_PREFIX: &'static str = "Members";
-}
-#[allow(type_alias_bounds)]
-type Members<T: V2ToV3> = StorageValue<__Members, Vec<SeatHolder<T::AccountId, T::Balance>>>;
-
-struct __RunnersUp;
-impl frame_support::traits::StorageInstance for __RunnersUp {
-	fn pallet_prefix() -> &'static str { "PhragmenElection" }
-	const STORAGE_PREFIX: &'static str = "RunnersUp";
-}
-#[allow(type_alias_bounds)]
-type RunnersUp<T: V2ToV3> = StorageValue<__RunnersUp, Vec<SeatHolder<T::AccountId, T::Balance>>>;
-
-struct __Voting;
-impl frame_support::traits::StorageInstance for __Voting {
-	fn pallet_prefix() -> &'static str { "PhragmenElection" }
-	const STORAGE_PREFIX: &'static str = "Voting";
-}
-#[allow(type_alias_bounds)]
-type Voting<T: V2ToV3> = StorageMap<__Voting, Twox64Concat, T::AccountId, Voter<T::AccountId, T::Balance>>;
+frame_support::generate_storage_alias!(
+	PhragmenElection, Candidates<T: V2ToV3> => Value<Vec<(T::AccountId, T::Balance)>>
+);
+frame_support::generate_storage_alias!(
+	PhragmenElection, Members<T: V2ToV3> => Value<Vec<SeatHolder<T::AccountId, T::Balance>>>
+);
+frame_support::generate_storage_alias!(
+	PhragmenElection, RunnersUp<T: V2ToV3> => Value<Vec<SeatHolder<T::AccountId, T::Balance>>>
+);
+frame_support::generate_storage_alias!(
+	PhragmenElection, Voting<T: V2ToV3> => Map<
+		(Twox64Concat, T::AccountId),
+		Voter<T::AccountId, T::Balance>
+	>
+);
 
 /// Apply all of the migrations from 2_0_0 to 3_0_0.
 ///
diff --git a/substrate/frame/staking/src/lib.rs b/substrate/frame/staking/src/lib.rs
index 0ec976e37712319563b808fe7fcaaf9555ccabf0..c28dbc87bccddd0597327e8e90c9c3e048f5f174 100644
--- a/substrate/frame/staking/src/lib.rs
+++ b/substrate/frame/staking/src/lib.rs
@@ -1036,30 +1036,15 @@ pub mod migrations {
 
 	pub mod v6 {
 		use super::*;
-		use frame_support::{traits::Get, weights::Weight, pallet_prelude::*};
-
-		macro_rules! generate_storage_types {
-			($name:ident => Value<$value:ty>) => {
-				paste::paste! {
-					struct [<$name Instance>];
-					impl frame_support::traits::StorageInstance for [<$name Instance>] {
-						fn pallet_prefix() -> &'static str {
-							"Staking"
-						}
-						const STORAGE_PREFIX: &'static str = stringify!($name);
-					}
-					type $name = StorageValue<[<$name Instance>], $value, ValueQuery>;
-				}
-			}
-		}
+		use frame_support::{traits::Get, weights::Weight, generate_storage_alias};
 
 		// NOTE: value type doesn't matter, we just set it to () here.
-		generate_storage_types!(SnapshotValidators => Value<()>);
-		generate_storage_types!(SnapshotNominators => Value<()>);
-		generate_storage_types!(QueuedElected => Value<()>);
-		generate_storage_types!(QueuedScore => Value<()>);
-		generate_storage_types!(EraElectionStatus => Value<()>);
-		generate_storage_types!(IsCurrentSessionFinal => Value<()>);
+		generate_storage_alias!(Staking, SnapshotValidators => Value<()>);
+		generate_storage_alias!(Staking, SnapshotNominators => Value<()>);
+		generate_storage_alias!(Staking, QueuedElected => Value<()>);
+		generate_storage_alias!(Staking, QueuedScore => Value<()>);
+		generate_storage_alias!(Staking, EraElectionStatus => Value<()>);
+		generate_storage_alias!(Staking, IsCurrentSessionFinal => Value<()>);
 
 		/// check to execute prior to migration.
 		pub fn pre_migrate<T: Config>() -> Result<(), &'static str> {
diff --git a/substrate/frame/support/src/lib.rs b/substrate/frame/support/src/lib.rs
index 220e7a06bdf3146cd1c4eb24b1889c9c8966c310..362c4c5a0a73bd267a856af0ac93f92caeeef008 100644
--- a/substrate/frame/support/src/lib.rs
+++ b/substrate/frame/support/src/lib.rs
@@ -87,6 +87,124 @@ pub const LOG_TARGET: &'static str = "runtime::frame-support";
 #[derive(Debug, PartialEq, Eq, Clone)]
 pub enum Never {}
 
+/// Generate a new type alias for [`storage::types::value::StorageValue`],
+/// [`storage::types::value::StorageMap`] and [`storage::types::value::StorageDoubleMap`].
+///
+/// Useful for creating a *storage-like* struct for test and migrations.
+///
+///```
+/// # use frame_support::generate_storage_alias;
+/// use frame_support::codec;
+/// use frame_support::Twox64Concat;
+/// // generate a storage value with type u32.
+/// generate_storage_alias!(Prefix, StorageName => Value<u32>);
+///
+/// // generate a double map from `(u32, u32)` (with hasher `Twox64Concat`) to `Vec<u8>`
+/// generate_storage_alias!(
+///		OtherPrefix, OtherStorageName => DoubleMap<
+/// 		(u32, u32),
+/// 		(u32, u32),
+/// 		Vec<u8>
+///		>
+/// );
+///
+/// // generate a map from `Config::AccountId` (with hasher `Twox64Concat`) to `Vec<u8>`
+/// trait Config { type AccountId: codec::FullCodec; }
+/// generate_storage_alias!(
+///		Prefix, GenericStorage<T: Config> => Map<(Twox64Concat, T::AccountId), Vec<u8>>
+/// );
+/// # fn main() {}
+///```
+#[macro_export]
+macro_rules! generate_storage_alias {
+	// without generic for $name.
+	($pallet:ident, $name:ident => Map<($key:ty, $hasher:ty), $value:ty>) => {
+		$crate::paste::paste! {
+			$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);
+			type $name = $crate::storage::types::StorageMap<
+				[<$name Instance>],
+				$hasher,
+				$key,
+				$value,
+			>;
+		}
+	};
+	($pallet:ident, $name:ident => DoubleMap<($key1:ty, $hasher1:ty), ($key2:ty, $hasher2:ty), $value:ty>) => {
+		$crate::paste::paste! {
+			$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);
+			type $name = $crate::storage::types::StorageMap<
+				[<$name Instance>],
+				$hasher1,
+				$key1,
+				$hasher2,
+				$key2,
+				$value,
+			>;
+		}
+	};
+	($pallet:ident, $name:ident => Value<$value:ty>) => {
+		$crate::paste::paste! {
+			$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);
+			type $name = $crate::storage::types::StorageValue<
+				[<$name Instance>],
+				$value,
+			>;
+		}
+	};
+	// with generic for $name.
+	($pallet:ident, $name:ident<$t:ident : $bounds:tt> => Map<($key:ty, $hasher:ty), $value:ty>) => {
+		$crate::paste::paste! {
+			$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);
+			#[allow(type_alias_bounds)]
+			type $name<$t : $bounds> = $crate::storage::types::StorageMap<
+				[<$name Instance>],
+				$key,
+				$hasher,
+				$value,
+			>;
+		}
+	};
+	(
+		$pallet:ident,
+		$name:ident<$t:ident : $bounds:tt>
+		=> DoubleMap<($key1:ty, $hasher1:ty), ($key2:ty, $hasher2:ty), $value:ty>)
+	=> {
+		$crate::paste::paste! {
+			$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);
+			#[allow(type_alias_bounds)]
+			type $name<$t : $bounds> = $crate::storage::types::StorageMap<
+				[<$name Instance>],
+				$key1,
+				$hasher1,
+				$key2,
+				$hasher2,
+				$value,
+			>;
+		}
+	};
+	($pallet:ident, $name:ident<$t:ident : $bounds:tt> => Value<$value:ty>) => {
+		$crate::paste::paste! {
+			$crate::generate_storage_alias!(@GENERATE_INSTANCE_STRUCT $pallet, $name);
+			#[allow(type_alias_bounds)]
+			type $name<$t : $bounds> = $crate::storage::types::StorageValue<
+				[<$name Instance>],
+				$value,
+				$crate::storage::types::ValueQuery,
+			>;
+		}
+	};
+	// helper used in all arms.
+	(@GENERATE_INSTANCE_STRUCT $pallet:ident, $name:ident) => {
+		$crate::paste::paste! {
+			struct [<$name Instance>];
+			impl $crate::traits::StorageInstance for [<$name Instance>] {
+				fn pallet_prefix() -> &'static str { stringify!($pallet) }
+				const STORAGE_PREFIX: &'static str = stringify!($name);
+			}
+		}
+	}
+}
+
 /// Create new implementations of the [`Get`](crate::traits::Get) trait.
 ///
 /// The so-called parameter type can be created in four different ways: