diff --git a/Cargo.lock b/Cargo.lock
index 68eeac71..6662c493 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -12,6 +12,21 @@ dependencies = [
"regex",
]
+[[package]]
+name = "addr2line"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
[[package]]
name = "ahash"
version = "0.8.11"
@@ -79,6 +94,21 @@ version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
+[[package]]
+name = "backtrace"
+version = "0.3.73"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
[[package]]
name = "base64"
version = "0.13.1"
@@ -394,6 +424,12 @@ dependencies = [
"wasi",
]
+[[package]]
+name = "gimli"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
+
[[package]]
name = "hash32"
version = "0.3.1"
@@ -544,6 +580,15 @@ version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+[[package]]
+name = "miniz_oxide"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
+dependencies = [
+ "adler",
+]
+
[[package]]
name = "new_debug_unreachable"
version = "1.0.6"
@@ -585,6 +630,15 @@ dependencies = [
"autocfg",
]
+[[package]]
+name = "object"
+version = "0.36.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "once_cell"
version = "1.19.0"
@@ -761,6 +815,12 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
+[[package]]
+name = "rustc-demangle"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
+
[[package]]
name = "rustc-hash"
version = "1.1.0"
@@ -1137,6 +1197,16 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+[[package]]
+name = "tokio"
+version = "1.40.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998"
+dependencies = [
+ "backtrace",
+ "pin-project-lite",
+]
+
[[package]]
name = "tracing"
version = "0.1.40"
@@ -1196,6 +1266,7 @@ dependencies = [
"serde_json",
"smol_str",
"thiserror",
+ "tokio",
"ts-rs-macros",
"url",
"uuid",
diff --git a/README.md b/README.md
index 39cf0ee1..434edb97 100644
--- a/README.md
+++ b/README.md
@@ -87,6 +87,7 @@ When running `cargo test`, the TypeScript bindings will be exported to the file
| heapless-impl | Implement `TS` for types from *heapless* |
| semver-impl | Implement `TS` for types from *semver* |
| smol_str-impl | Implement `TS` for types from *smol_str* |
+| tokio-impl | Implement `TS` for types from *tokio* |
diff --git a/ts-rs/Cargo.toml b/ts-rs/Cargo.toml
index 40fb110d..a6592441 100644
--- a/ts-rs/Cargo.toml
+++ b/ts-rs/Cargo.toml
@@ -35,11 +35,13 @@ smol_str-impl = ["smol_str"]
serde-json-impl = ["serde_json"]
no-serde-warnings = ["ts-rs-macros/no-serde-warnings"]
import-esm = []
+tokio-impl = ["tokio"]
[dev-dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1"
chrono = { version = "0.4", features = ["serde"] }
+tokio = { version = "1.40", features = ["sync", "rt"] }
[dependencies]
heapless = { version = ">= 0.7, < 0.9", optional = true }
@@ -54,10 +56,10 @@ bson = { version = "2", optional = true }
bytes = { version = "1", optional = true }
url = { version = "2", optional = true }
semver = { version = "1", optional = true }
-smol_str = { version = "0.3", optional = true }
+smol_str = { version = "0.3", optional = true }
thiserror = "1"
indexmap = { version = "2", optional = true }
ordered-float = { version = ">= 3, < 5", optional = true }
serde_json = { version = "1", optional = true }
lazy_static = { version = "1", default-features = false }
-
+tokio = { version = "1", features = ["sync"], optional = true }
diff --git a/ts-rs/src/lib.rs b/ts-rs/src/lib.rs
index 9dc0522e..c49a83cf 100644
--- a/ts-rs/src/lib.rs
+++ b/ts-rs/src/lib.rs
@@ -85,6 +85,7 @@
//! | heapless-impl | Implement `TS` for types from *heapless* |
//! | semver-impl | Implement `TS` for types from *semver* |
//! | smol_str-impl | Implement `TS` for types from *smol_str* |
+//! | tokio-impl | Implement `TS` for types from *tokio* |
//!
//!
//!
@@ -138,6 +139,8 @@ mod chrono;
mod export;
#[cfg(feature = "serde-json-impl")]
mod serde_json;
+#[cfg(feature = "tokio-impl")]
+mod tokio;
/// A type which can be represented in TypeScript.
/// Most of the time, you'd want to derive this trait instead of implementing it manually.
@@ -987,6 +990,7 @@ impl_wrapper!(impl<'a, T: TS + ToOwned + ?Sized> TS for std::borrow::Cow<'a, T>)
impl_wrapper!(impl TS for std::cell::Cell);
impl_wrapper!(impl TS for std::cell::RefCell);
impl_wrapper!(impl TS for std::sync::Mutex);
+impl_wrapper!(impl TS for std::sync::RwLock);
impl_wrapper!(impl TS for std::sync::Weak);
impl_wrapper!(impl TS for std::marker::PhantomData);
@@ -1053,6 +1057,8 @@ impl_primitives! {
pub(crate) use impl_primitives;
#[rustfmt::skip]
pub(crate) use impl_shadow;
+#[rustfmt::skip]
+pub(crate) use impl_wrapper;
#[doc(hidden)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
diff --git a/ts-rs/src/tokio.rs b/ts-rs/src/tokio.rs
new file mode 100644
index 00000000..0d90e0a2
--- /dev/null
+++ b/ts-rs/src/tokio.rs
@@ -0,0 +1,7 @@
+use tokio::sync::{Mutex, OnceCell, RwLock};
+
+use super::{impl_wrapper, TypeVisitor, TS};
+
+impl_wrapper!(impl TS for Mutex);
+impl_wrapper!(impl TS for OnceCell);
+impl_wrapper!(impl TS for RwLock);
diff --git a/ts-rs/tests/integration/main.rs b/ts-rs/tests/integration/main.rs
index 05c3234d..662df57d 100644
--- a/ts-rs/tests/integration/main.rs
+++ b/ts-rs/tests/integration/main.rs
@@ -52,6 +52,7 @@ mod skip;
mod slices;
mod struct_rename;
mod struct_tag;
+mod tokio;
mod top_level_type_as;
mod top_level_type_override;
mod tuple;
diff --git a/ts-rs/tests/integration/tokio.rs b/ts-rs/tests/integration/tokio.rs
new file mode 100644
index 00000000..ac31371f
--- /dev/null
+++ b/ts-rs/tests/integration/tokio.rs
@@ -0,0 +1,21 @@
+#![cfg(feature = "tokio-impl")]
+
+use tokio::sync::{Mutex, OnceCell, RwLock};
+use ts_rs::TS;
+
+#[derive(TS)]
+#[ts(export, export_to = "tokio/")]
+#[ts(concrete(T = i32))]
+struct Tokio {
+ mutex: Mutex,
+ once_cell: OnceCell,
+ rw_lock: RwLock,
+}
+
+#[test]
+fn tokio() {
+ assert_eq!(
+ Tokio::::decl(),
+ "type Tokio = { mutex: number, once_cell: number, rw_lock: number, };"
+ )
+}