diff --git a/System/OsString/Internal/Types.hs b/System/OsString/Internal/Types.hs
--- a/System/OsString/Internal/Types.hs
+++ b/System/OsString/Internal/Types.hs
@@ -2,7 +2,7 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE PackageImports #-}
 {-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TemplateHaskellQuotes #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeApplications #-}
@@ -46,9 +46,7 @@
 import System.OsString.Encoding.Internal
 import qualified System.OsString.Data.ByteString.Short as BS
 import qualified System.OsString.Data.ByteString.Short.Word16 as BS16
-#if MIN_VERSION_template_haskell(2,16,0)
 import qualified Language.Haskell.TH.Syntax as TH
-#endif
 
 -- Using unpinned bytearrays to avoid Heap fragmentation and
 -- which are reasonably cheap to pass to FFI calls
@@ -77,8 +75,7 @@
 
 
 instance Lift WindowsString where
-  lift (WindowsString bs)
-    = [| WindowsString (BS.pack $(lift $ BS.unpack bs)) :: WindowsString |]
+  lift (WindowsString bs) = TH.AppE (TH.ConE 'WindowsString) <$> (lift bs)
 #if MIN_VERSION_template_haskell(2,17,0)
   liftTyped = TH.unsafeCodeCoerce . TH.lift
 #elif MIN_VERSION_template_haskell(2,16,0)
@@ -103,8 +100,7 @@
 #endif
 
 instance Lift PosixString where
-  lift (PosixString bs)
-    = [| PosixString (BS.pack $(lift $ BS.unpack bs)) :: PosixString |]
+  lift (PosixString bs) = TH.AppE (TH.ConE 'PosixString) <$> (lift bs)
 #if MIN_VERSION_template_haskell(2,17,0)
   liftTyped = TH.unsafeCodeCoerce . TH.lift
 #elif MIN_VERSION_template_haskell(2,16,0)
@@ -185,7 +181,7 @@
 #if MIN_VERSION_base(4,11,0)
     mappend = (<>)
 #else
-    mappend = coerce (mappend :: BS.ShortByteString -> BS.ShortByteString -> BS.ShortByteString))
+    mappend = coerce (mappend :: BS.ShortByteString -> BS.ShortByteString -> BS.ShortByteString)
 #endif
 
 #if MIN_VERSION_base(4,11,0)
@@ -197,9 +193,9 @@
 instance Lift OsString where
   lift xs = case coercionToPlatformTypes of
     Left (_, co) ->
-      [| OsString (WindowsString (BS.pack $(lift $ BS.unpack $ coerce $ coerceWith co xs))) :: OsString |]
-    Right (_, co) ->
-      [| OsString (PosixString (BS.pack $(lift $ BS.unpack $ coerce $ coerceWith co xs))) :: OsString |]
+      TH.AppE (TH.ConE 'OsString) <$> (lift $ coerceWith co xs)
+    Right (_, co) -> do
+      TH.AppE (TH.ConE 'OsString) <$> (lift $ coerceWith co xs)
 #if MIN_VERSION_template_haskell(2,17,0)
   liftTyped = TH.unsafeCodeCoerce . TH.lift
 #elif MIN_VERSION_template_haskell(2,16,0)
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,9 @@
 # Changelog for [`os-string` package](http://hackage.haskell.org/package/os-string)
 
+## 2.0.4 *Jun 2024*
+
+* Use TemplateHaskellQuotes rather than TemplateHaskell extension wrt [#21](https://github.com/haskell/os-string/issues/21)
+
 ## 2.0.3 *May 2024*
 
 * Fix `length` function wrt [#17](https://github.com/haskell/os-string/issues/17)
diff --git a/os-string.cabal b/os-string.cabal
--- a/os-string.cabal
+++ b/os-string.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.2
 name:               os-string
-version:            2.0.3
+version:            2.0.4
 
 -- NOTE: Don't forget to update ./changelog.md
 license:            BSD-3-Clause
