#![allow(dead_code)] use std::{ collections::{BTreeMap, HashSet}, fmt::Debug, rc::Rc, }; use ts_rs::TS; #[derive(TS)] struct Generic where T: TS, { value: T, values: Vec, } #[derive(TS)] struct GenericAutoBound { value: T, values: Vec, } #[derive(TS)] struct GenericAutoBound2 where T: PartialEq, { value: T, values: Vec, } #[derive(TS)] struct Container { foo: Generic, bar: Box>>, baz: Box>>>, } macro_rules! declare { ($(#[$meta:meta])* $name:ident { $($fident:ident: $t:ty),+ $(,)? }) => { $(#[$meta])* struct $name { $(pub $fident: $t),+ } } } declare! { #[derive(TS)] TypeGroup { foo: Vec, } } #[test] fn test() { assert_eq!( TypeGroup::decl(), "interface TypeGroup { foo: Array, }", ); assert_eq!( Generic::<()>::decl(), "interface Generic { value: T, values: Array, }" ); assert_eq!( GenericAutoBound::<()>::decl(), "interface GenericAutoBound { value: T, values: Array, }" ); assert_eq!( GenericAutoBound2::<()>::decl(), "interface GenericAutoBound2 { value: T, values: Array, }" ); assert_eq!( Container::decl(), "interface Container { foo: Generic, bar: Array>, baz: Record>, }" ); } #[test] fn generic_enum() { #[derive(TS)] enum Generic { A(A), B(B, B, B), C(Vec), D(Vec>>), E { a: A, b: B, c: C }, X(Vec), Y(i32), Z(Vec>), } assert_eq!( Generic::<(), (), ()>::decl(), r#"type Generic = { "A": A } | { "B": [B, B, B] } | { "C": Array } | { "D": Array>> } | { "E": { a: A, b: B, c: C, } } | { "X": Array } | { "Y": number } | { "Z": Array> };"# ) } #[test] fn generic_newtype() { #[derive(TS)] struct NewType(Vec>); assert_eq!( NewType::<()>::decl(), r#"type NewType = Array>;"# ); } #[test] fn generic_tuple() { #[derive(TS)] struct Tuple(T, Vec, Vec>); assert_eq!( Tuple::<()>::decl(), r#"type Tuple = [T, Array, Array>];"# ); } #[test] fn generic_struct() { #[derive(TS)] struct Struct { a: T, b: (T, T), c: (T, (T, T)), d: [T; 3], e: [(T, T); 3], f: Vec, g: Vec>, h: Vec<[(T, T); 3]>, } assert_eq!( Struct::<()>::decl(), "interface Struct { a: T, b: [T, T], c: [T, [T, T]], d: Array, e: Array<[T, T]>, f: Array, g: Array>, h: Array>, }" ) } #[test] #[ignore] // https://github.com/Aleph-Alpha/ts-rs/issues/56 TODO fn inline() { #[derive(TS)] struct Generic { t: T, } #[derive(TS)] struct Container { g: Generic, #[ts(inline)] gi: Generic, #[ts(flatten)] t: Generic, } assert_eq!(Generic::<()>::decl(), "interface Generic { t: T, }"); assert_eq!( Container::decl(), "interface Container { g: Generic, gi: { t: string }, t: string, }" ); } #[test] fn default() { #[derive(TS)] struct A { t: T, } assert_eq!(A::<()>::decl(), "interface A { t: T, }"); #[derive(TS)] struct B>> { u: U, } assert_eq!( B::<()>::decl(), "interface B | null> { u: U, }" ); assert!(B::<()>::dependencies().iter().any(|dep| dep.ts_name == "A")); #[derive(TS)] struct Y { a1: A, a2: A, // https://github.com/Aleph-Alpha/ts-rs/issues/56 // TODO: fixme // #[ts(inline)] // xi: X, // #[ts(inline)] // xi2: X } assert_eq!(Y::decl(), "interface Y { a1: A, a2: A, }") } #[test] fn trait_bounds() { #[derive(TS)] struct A { t: T, } assert_eq!(A::::decl(), "interface A { t: T, }"); #[derive(TS)] struct B(T); assert_eq!(B::<&'static str>::decl(), "type B = T;"); #[derive(TS)] enum C { A { t: T }, B(T), C, D(T, K), } assert_eq!( C::<&'static str, i32>::decl(), r#"type C = { "A": { t: T, } } | { "B": T } | "C" | { "D": [T, K] };"# ); #[derive(TS)] struct D { t: [T; N], } assert_eq!(D::<&str, 41>::decl(), "interface D { t: Array, }") }