oag_node_client/
type_mapper.rs1use oag_core::ir::IrType;
2
3pub fn ir_type_to_ts(ir_type: &IrType) -> String {
5 match ir_type {
6 IrType::String => "string".to_string(),
7 IrType::Number => "number".to_string(),
8 IrType::Integer => "number".to_string(),
9 IrType::Boolean => "boolean".to_string(),
10 IrType::Null => "null".to_string(),
11 IrType::DateTime => "string".to_string(),
12 IrType::Binary => "Blob".to_string(),
13 IrType::Any => "unknown".to_string(),
14 IrType::Void => "void".to_string(),
15 IrType::Ref(name) => name.clone(),
16 IrType::Array(inner) => {
17 let inner_ts = ir_type_to_ts(inner);
18 if inner_ts.contains('|') {
19 format!("({inner_ts})[]")
20 } else {
21 format!("{inner_ts}[]")
22 }
23 }
24 IrType::Map(value_type) => {
25 let value_ts = ir_type_to_ts(value_type);
26 format!("Record<string, {value_ts}>")
27 }
28 IrType::Object(fields) => {
29 if fields.is_empty() {
30 return "Record<string, unknown>".to_string();
31 }
32 let field_strs: Vec<String> = fields
33 .iter()
34 .map(|(name, ty, required)| {
35 let ts_type = ir_type_to_ts(ty);
36 if *required {
37 format!("{name}: {ts_type}")
38 } else {
39 format!("{name}?: {ts_type}")
40 }
41 })
42 .collect();
43 format!("{{ {} }}", field_strs.join("; "))
44 }
45 IrType::Union(variants) => {
46 let variant_strs: Vec<String> = variants.iter().map(ir_type_to_ts).collect();
47 variant_strs.join(" | ")
48 }
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn test_primitives() {
58 assert_eq!(ir_type_to_ts(&IrType::String), "string");
59 assert_eq!(ir_type_to_ts(&IrType::Number), "number");
60 assert_eq!(ir_type_to_ts(&IrType::Integer), "number");
61 assert_eq!(ir_type_to_ts(&IrType::Boolean), "boolean");
62 assert_eq!(ir_type_to_ts(&IrType::Null), "null");
63 assert_eq!(ir_type_to_ts(&IrType::Any), "unknown");
64 assert_eq!(ir_type_to_ts(&IrType::Void), "void");
65 }
66
67 #[test]
68 fn test_array() {
69 assert_eq!(
70 ir_type_to_ts(&IrType::Array(Box::new(IrType::String))),
71 "string[]"
72 );
73 assert_eq!(
74 ir_type_to_ts(&IrType::Array(Box::new(IrType::Union(vec![
75 IrType::String,
76 IrType::Number,
77 ])))),
78 "(string | number)[]"
79 );
80 }
81
82 #[test]
83 fn test_map() {
84 assert_eq!(
85 ir_type_to_ts(&IrType::Map(Box::new(IrType::String))),
86 "Record<string, string>"
87 );
88 }
89
90 #[test]
91 fn test_ref() {
92 assert_eq!(ir_type_to_ts(&IrType::Ref("Pet".to_string())), "Pet");
93 }
94
95 #[test]
96 fn test_union() {
97 assert_eq!(
98 ir_type_to_ts(&IrType::Union(vec![IrType::String, IrType::Number])),
99 "string | number"
100 );
101 }
102}