Type alias code generation
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 6eac0d9..e3026ba 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -3,7 +3,7 @@
 use crate::syntax::report::Errors;
 use crate::syntax::symbol::Symbol;
 use crate::syntax::{
-    self, check, mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types,
+    self, check, mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, TypeAlias, Types,
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -46,7 +46,7 @@
             Api::Enum(enm) => expanded.extend(expand_enum(enm)),
             Api::CxxType(ety) => {
                 if !types.enums.contains_key(&ety.ident) {
-                    expanded.extend(expand_cxx_type(ety));
+                    expanded.extend(expand_cxx_type(namespace, ety));
                 }
             }
             Api::CxxFunction(efn) => {
@@ -55,7 +55,10 @@
             Api::RustFunction(efn) => {
                 hidden.extend(expand_rust_function_shim(namespace, efn, types))
             }
-            Api::TypeAlias(_alias) => unimplemented!(),
+            Api::TypeAlias(alias) => {
+                expanded.extend(expand_type_alias(alias));
+                hidden.extend(expand_type_alias_verify(namespace, alias));
+            }
         }
     }
 
@@ -162,15 +165,21 @@
     }
 }
 
-fn expand_cxx_type(ety: &ExternType) -> TokenStream {
+fn expand_cxx_type(namespace: &Namespace, ety: &ExternType) -> TokenStream {
     let ident = &ety.ident;
     let doc = &ety.doc;
+    let type_id = type_id(namespace, ident);
+
     quote! {
         #doc
         #[repr(C)]
         pub struct #ident {
             _private: ::cxx::private::Opaque,
         }
+
+        unsafe impl ::cxx::ExternType for #ident {
+            type Id = #type_id;
+        }
     }
 }
 
@@ -555,6 +564,35 @@
     }
 }
 
+fn expand_type_alias(alias: &TypeAlias) -> TokenStream {
+    let ident = &alias.ident;
+    let ty = &alias.ty;
+    quote! {
+        pub type #ident = #ty;
+    }
+}
+
+fn expand_type_alias_verify(namespace: &Namespace, alias: &TypeAlias) -> TokenStream {
+    let ident = &alias.ident;
+    let type_id = type_id(namespace, ident);
+    quote! {
+        const _: fn() = ::cxx::private::verify_extern_type::<#ident, #type_id>;
+    }
+}
+
+fn type_id(namespace: &Namespace, ident: &Ident) -> TokenStream {
+    let mut path = String::new();
+    for name in namespace {
+        path += &name.to_string();
+        path += "::";
+    }
+    path += &ident.to_string();
+
+    quote! {
+        ::cxx::type_id!(#path)
+    }
+}
+
 fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
     let link_prefix = format!("cxxbridge03$box${}{}$", namespace, ident);
     let link_uninit = format!("{}uninit", link_prefix);