Serialization
The serialization API converts runtime annotated types to and from a plain JSON format. This enables transferring type definitions between backend and frontend, storing them in databases, or caching compiled types.
import {
serializeAnnotatedType,
deserializeAnnotatedType,
buildJsonSchema,
} from '@atscript/typescript/utils'Purpose
Serialize type definitions on the server and send them to the client. The client deserializes them and uses them for validation, live form tools, or schema-driven UI helpers without bundling the original .as files.
Basic Usage
import { Product } from './product.as'
// Serialize to a JSON-safe object
const serialized = serializeAnnotatedType(Product)
const json = JSON.stringify(serialized)
// ... transmit, store, or cache ...
// Deserialize back to a live type
const restored = deserializeAnnotatedType(JSON.parse(json))
// The restored type is fully functional
restored.validator().validate(data)
buildJsonSchema(restored)Deserialized Types Are Live
A deserialized type is a fully functional TAtscriptAnnotatedType:
.validator()creates a workingValidatorinstance- Works with
buildJsonSchema()andforAnnotatedType() isAnnotatedType()returnstrue- Metadata is accessible via
.metadata.get() - The
idfield (type name) is preserved through serialization, sobuildJsonSchemawill still produce$defs/$reffor deserialized types
Versioning
The serialized output includes a $v field with the format version (currently 1). If the format changes in a future release, deserializeAnnotatedType() will throw when it encounters an incompatible version, so you know to re-serialize from the source types.
import { SERIALIZE_VERSION } from '@atscript/typescript/utils'
// SERIALIZE_VERSION === 1Filtering Annotations
Use TSerializeOptions to control which annotations are included in the output. This is useful for stripping sensitive or server-only metadata before sending types to the client.
Strip specific annotations:
const serialized = serializeAnnotatedType(Product, {
ignoreAnnotations: ['db.table', 'db.mongo.collection'],
})Transform annotations with a callback:
const serialized = serializeAnnotatedType(Product, {
processAnnotation({ key, value, path, kind }) {
// Only keep meta.*, expect.*, and ui.* annotations
if (key.startsWith('meta.') || key.startsWith('expect.') || key.startsWith('ui.')) {
return { key, value }
}
// Return undefined to strip
},
})The processAnnotation callback receives:
key— annotation name (e.g.'meta.label')value— annotation valuepath— property path as astring[]array (e.g.['address', 'city'])kind— type kind at this node ('','object','array', etc.)
Example: Server-Driven Field Tools
A practical use case: the server serializes a type definition and the client uses it to build a field list with labels and placeholders.
Server (Express endpoint):
import { User } from './user.as'
import { serializeAnnotatedType } from '@atscript/typescript/utils'
app.get('/api/form/user', (req, res) => {
const schema = serializeAnnotatedType(User, {
ignoreAnnotations: ['db.table', 'db.mongo.collection'], // strip server-only metadata
})
res.json(schema)
})Client (Vue component):
<script setup>
import { ref, onMounted } from 'vue'
import { deserializeAnnotatedType } from '@atscript/typescript/utils'
const fields = ref([])
const formData = ref({})
onMounted(async () => {
const res = await fetch('/api/form/user')
const type = deserializeAnnotatedType(await res.json())
// Build UI field data from type metadata
for (const [name, prop] of type.type.props.entries()) {
fields.value.push({
name,
label: prop.metadata.get('meta.label') || name,
placeholder: prop.metadata.get('ui.placeholder') || '',
})
formData.value[name] = ''
}
})
</script>
<template>
<form>
<div v-for="field in fields" :key="field.name">
<label>{{ field.label }}</label>
<input v-model="formData[field.name]" :placeholder="field.placeholder" />
</div>
</form>
</template>The field list, labels, and placeholders are all driven by annotations defined in the .as file, so the client does not need to duplicate that configuration.
Next Steps
- Type Definitions — the annotated type system
- Validation — validate data against types
- Metadata — access annotations at runtime