diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 8d7c8083..4b42143b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -146,4 +146,4 @@ jobs:
           RUSTDOCFLAGS: '-D warnings'
         with:
           command: doc
-          args: --all --no-deps  --document-private-items
+          args: --all --no-deps  --document-private-items --features typenum
diff --git a/.github/workflows/rustdoc.yml b/.github/workflows/rustdoc.yml
index f61a8ab5..83923d17 100644
--- a/.github/workflows/rustdoc.yml
+++ b/.github/workflows/rustdoc.yml
@@ -24,7 +24,7 @@ jobs:
         name: build docs
         with:
           command: doc
-          args: --all --no-deps
+          args: --all --no-deps --features typenum
 
       - uses: peaceiris/actions-gh-pages@v4
         name: push docs
diff --git a/Cargo.toml b/Cargo.toml
index dab64399..b1e3cdb6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "frunk"
 edition = "2021"
-version = "0.4.2"
+version = "0.5.0"
 authors = ["Lloyd <lloydmeta@gmail.com>"]
 description = "Frunk provides developers with a number of functional programming tools like HList, Coproduct, Generic, LabelledGeneric, Validated, Monoid, Semigroup and friends."
 license = "MIT"
@@ -19,7 +19,7 @@ time = "0.3"
 [dependencies.frunk_core]
 path = "core"
 default-features = false
-version = "0.4.2"
+version = "0.5.0"
 
 [dependencies.frunk_proc_macros]
 path = "proc-macros"
@@ -45,6 +45,7 @@ default = ["validated", "proc-macros"]
 validated = ["std"]
 proc-macros = ["frunk_proc_macros"]
 std = ["frunk_core/std"]
+typenum = ["frunk_core/typenum"]
 
 [profile.bench]
 opt-level = 3
diff --git a/core/Cargo.toml b/core/Cargo.toml
index afc58b1b..bb8dbc97 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "frunk_core"
 edition = "2021"
-version = "0.4.2"
+version = "0.5.0"
 authors = ["Lloyd <lloydmeta@gmail.com>"]
 description = "Frunk core provides developers with HList, Coproduct, LabelledGeneric and Generic"
 license = "MIT"
@@ -15,9 +15,11 @@ travis-ci = { repository = "lloydmeta/frunk" }
 [features]
 default = ["std"]
 std = []
+typenum = ["dep:typenum"]
 
 [dependencies]
 serde = { version = "^1.0", optional = true, features = [ "derive" ] }
+typenum = { version = "1.17.0", optional = true }
 
 [dev-dependencies.frunk_derives]
 path = "../derives"
@@ -27,7 +29,7 @@ version = "0.4.1"
 [dev-dependencies.frunk]
 path = ".."
 default-features = false
-version = "0.4.2"
+version = "0.5.0"
 
 [dev-dependencies.frunk_proc_macros]
 path = "../proc-macros"
diff --git a/core/src/hlist.rs b/core/src/hlist.rs
index 2fdee009..5284ae29 100644
--- a/core/src/hlist.rs
+++ b/core/src/hlist.rs
@@ -60,6 +60,11 @@ use crate::traits::{Func, IntoReverse, Poly, ToMut, ToRef};
 #[cfg(feature = "serde")]
 use serde::{Deserialize, Serialize};
 
+#[cfg(feature = "typenum")]
+pub use typenum;
+#[cfg(feature = "typenum")]
+use typenum::{bit::B1, Add1, Unsigned, U0};
+
 use std::ops::Add;
 
 /// Typeclass for HList-y behaviour
@@ -67,18 +72,58 @@ use std::ops::Add;
 /// An HList is a heterogeneous list, one that is statically typed at compile time. In simple terms,
 /// it is just an arbitrarily-nested Tuple2.
 pub trait HList: Sized {
-    /// Returns the length of a given HList type without making use of any references, or
-    /// in fact, any values at all.
+    /// The type-level encapsulation of the lists length, using `typenum` under the hood.
     ///
     /// # Examples
     /// ```
     /// # fn main() {
+    /// use frunk_core::hlist::typenum::{self, Unsigned };
     /// use frunk::prelude::*;
     /// use frunk_core::HList;
     ///
-    /// assert_eq!(<HList![i32, bool, f32]>::LEN, 3);
+    /// type LenThree = HList![bool, (), u8];
+    /// type LenTwo = HList![bool, ()];
+    ///
+    /// // Attach a constraint that ensures constraints are met at type-check time
+    /// fn type_len_constraint<T: typenum::IsLess<typenum::U3, Output = typenum::True>>() {}
+    ///
+    ///
+    ///
+    /// // Won't compile: the length of LenThree doesn't meet the less-than-3 requirement
+    /// // let _fail = type_len_constraint::<<LenThree as HList>::Len>();
+    /// let _is_good = type_len_constraint::<<LenTwo   as HList>::Len>();
+    ///
+    /// // Pull out the length of the list in the word-size of your choosing.
+    /// let byte: u8 = <<LenThree as HList>::Len>::U8;
+    /// let u_16: u16 = <<LenThree as HList>::Len>::U16;
+    ///
+    ///
+    /// assert_eq!(<LenThree as HList>::Len::U8, 3u8);
+    /// # }
+    /// ```
+    ///
+    /// ```compile_fail
+    /// # fn main() {
+    /// use frunk_core::hlist::typenum::{self, Unsigned };
+    /// use frunk::prelude::*;
+    /// use frunk_core::HList;
+    ///
+    /// type LenThree = HList![bool, (), u8];
+    /// type LenTwo = HList![bool, ()];
+    ///
+    /// // Attach a constraint that ensures constraints are met at type-check time
+    /// fn type_len_constraint<T: typenum::IsLess<typenum::U3, Output = typenum::True>>() {}
+    ///
+    ///
+    ///
+    /// // Won't compile: the length of LenThree doesn't meet the less-than-3 requirement
+    /// let _ = type_len_constraint::<<LenThree as HList>::Len>();
     /// # }
     /// ```
+    #[cfg(feature = "typenum")]
+    type Len: Unsigned;
+
+    /// Length as a usize const generic. Is equivilent to `<Self as HList>::LEN::USIZE`
     const LEN: usize;
 
     /// Returns the length of a given HList
@@ -115,21 +160,6 @@ pub trait HList: Sized {
         Self::LEN == 0
     }
 
-    /// Returns the length of a given HList type without making use of any references, or
-    /// in fact, any values at all.
-    ///
-    /// # Examples
-    /// ```
-    /// # fn main() {
-    /// use frunk::prelude::*;
-    /// use frunk_core::HList;
-    ///
-    /// assert_eq!(<HList![i32, bool, f32]>::static_len(), 3);
-    /// # }
-    /// ```
-    #[deprecated(since = "0.1.31", note = "Please use LEN instead")]
-    fn static_len() -> usize;
-
     /// Prepends an item to the current HList
     ///
     /// # Examples
@@ -168,10 +198,10 @@ pub trait HList: Sized {
 pub struct HNil;
 
 impl HList for HNil {
+    #[cfg(feature = "typenum")]
+    type Len = U0;
+
     const LEN: usize = 0;
-    fn static_len() -> usize {
-        Self::LEN
-    }
 }
 
 /// Represents the most basic non-empty HList. Its value is held in `head`
@@ -183,11 +213,18 @@ pub struct HCons<H, T> {
     pub tail: T,
 }
 
+#[cfg(feature = "typenum")]
+impl<H, T: HList> HList for HCons<H, T>
+where
+    <T as HList>::Len: Add<B1>,
+    <<T as HList>::Len as Add<B1>>::Output: Unsigned,
+{
+    type Len = <<T as HList>::Len as Add<B1>>::Output;
+    const LEN: usize = 1 + <T as HList>::LEN;
+}
+#[cfg(not(feature = "typenum"))]
 impl<H, T: HList> HList for HCons<H, T> {
     const LEN: usize = 1 + <T as HList>::LEN;
-    fn static_len() -> usize {
-        Self::LEN
-    }
 }
 
 impl<H, T> HCons<H, T> {
@@ -1120,9 +1157,25 @@ impl HZippable<HNil> for HNil {
     }
 }
 
+#[cfg(not(feature = "typenum"))]
+impl<H1, T1, H2, T2> HZippable<HCons<H2, T2>> for HCons<H1, T1>
+where
+    T1: HZippable<T2>,
+{
+    type Zipped = HCons<(H1, H2), T1::Zipped>;
+    fn zip(self, other: HCons<H2, T2>) -> Self::Zipped {
+        HCons {
+            head: (self.head, other.head),
+            tail: self.tail.zip(other.tail),
+        }
+    }
+}
+#[cfg(feature = "typenum")]
 impl<H1, T1, H2, T2> HZippable<HCons<H2, T2>> for HCons<H1, T1>
 where
     T1: HZippable<T2>,
+    <<T1 as HZippable<T2>>::Zipped as HList>::Len: Add<B1>,
+    Add1<<<T1 as HZippable<T2>>::Zipped as HList>::Len>: Unsigned,
 {
     type Zipped = HCons<(H1, H2), T1::Zipped>;
     fn zip(self, other: HCons<H2, T2>) -> Self::Zipped {
@@ -1433,6 +1486,26 @@ where
     }
 }
 
+#[cfg(feature = "typenum")]
+#[cfg(feature = "std")]
+#[allow(clippy::from_over_into)]
+impl<H, Tail> Into<Vec<H>> for HCons<H, Tail>
+where
+    Tail: Into<Vec<H>> + HList,
+    <Tail as HList>::Len: Add<B1>,
+    Add1<<Tail as HList>::Len>: Unsigned,
+{
+    fn into(self) -> Vec<H> {
+        let h = self.head;
+        let t = self.tail;
+        let mut v = Vec::with_capacity(<Self as HList>::LEN);
+        v.push(h);
+        let mut t_vec: Vec<H> = t.into();
+        v.append(&mut t_vec);
+        v
+    }
+}
+#[cfg(not(feature = "typenum"))]
 #[cfg(feature = "std")]
 #[allow(clippy::from_over_into)]
 impl<H, Tail> Into<Vec<H>> for HCons<H, Tail>
@@ -1905,6 +1978,8 @@ mod tests {
 
     #[test]
     fn test_len_const() {
+        #[cfg(feature = "typenum")]
+        assert_eq!(<HList![usize, &str, f32] as HList>::Len::USIZE, 3);
         assert_eq!(<HList![usize, &str, f32] as HList>::LEN, 3);
     }
 
diff --git a/laws/Cargo.toml b/laws/Cargo.toml
index 576948b6..42280264 100644
--- a/laws/Cargo.toml
+++ b/laws/Cargo.toml
@@ -15,7 +15,7 @@ travis-ci = { repository = "lloydmeta/frunk" }
 [dependencies.frunk]
 path = ".."
 default-features = false
-version = "0.4.2"
+version = "0.5.0"
 
 [dependencies]
 quickcheck = "1.0.3"
diff --git a/proc-macro-helpers/Cargo.toml b/proc-macro-helpers/Cargo.toml
index a58542f5..67fd7558 100644
--- a/proc-macro-helpers/Cargo.toml
+++ b/proc-macro-helpers/Cargo.toml
@@ -20,4 +20,4 @@ proc-macro2 = "1"
 [dependencies.frunk_core]
 path = "../core"
 default-features = false
-version = "0.4.2"
+version = "0.5.0"
diff --git a/proc-macros/Cargo.toml b/proc-macros/Cargo.toml
index b190ef27..1c2b3070 100644
--- a/proc-macros/Cargo.toml
+++ b/proc-macros/Cargo.toml
@@ -23,7 +23,7 @@ proc-macro = true
 [dependencies.frunk_core]
 path = "../core"
 default-features = false
-version = "0.4.2"
+version = "0.5.0"
 
 [dependencies.frunk_proc_macro_helpers]
 path = "../proc-macro-helpers"