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