stencil

Generate idiomatic types from JSON samples.
JSON Sample(s) → Inferrer → Intermediate Schema → Language Generator → Code
Supports TypeScript and Go. The intermediate schema is language-agnostic so more targets can be added later.
Install
go install github.com/justinwilliams-io/stencil/cmd/stencil@v0.2.0
Or build from source:
git clone https://github.com/justinwilliams-io/stencil.git
cd stencil
go build -o stencil ./cmd/stencil
Usage
# version
stencil version
stencil -v
# stdin → stdout (TypeScript by default)
echo '{"id":1,"name":"a"}' | stencil --stdin -n User
# Go structs
echo '{"id":1,"name":"a"}' | stencil --stdin -l go -n User --package models
# files (merged as samples)
stencil -n User testdata/user.json testdata/user_partial.json
# both languages into a directory
stencil -n User -l ts,go -o ./gen --package models testdata/user.json
# array of objects = multiple samples
stencil -n Item testdata/mixed_types.json
Flags
| Flag |
Default |
Description |
-l, --lang |
ts |
Target languages (comma-separated): ts, go |
-n, --name |
Root (or filename) |
Root type name |
-o, --out |
(stdout) |
Output file or directory |
--stdin |
false |
Read JSON from stdin |
--nullable |
union |
union | optional | strict |
--package |
types (Go) |
Package name for Go output |
--just-types |
true |
Types only (no serializers) |
-v, --version |
|
Print version |
Null handling (--nullable)
| Mode |
Behavior |
union |
JSON null becomes T | null (TS) or *T (Go); missing keys become optional |
optional |
null and missing both become optional (null stripped where possible) |
strict |
null always stays visible in the type; missing → optional |
Examples
TypeScript
stencil -n User testdata/user.json testdata/user_partial.json
// Code generated by stencil. DO NOT EDIT.
export interface Profile {
active: boolean;
bio: string;
}
export interface User {
email?: string;
id: number;
name: string;
profile: Profile;
tags?: string[];
}
Go
stencil -l go -n User --package models testdata/user.json testdata/user_partial.json
// Code generated by stencil. DO NOT EDIT.
package models
type Profile struct {
Active bool `json:"active"`
Bio string `json:"bio"`
}
type User struct {
Email *string `json:"email,omitempty"`
ID int64 `json:"id"`
Name string `json:"name"`
Profile Profile `json:"profile"`
Tags []string `json:"tags,omitempty"`
}
Library layout
cmd/stencil/ CLI entrypoint
internal/cli/ Cobra commands
internal/infer/ JSON → intermediate schema (+ merge)
internal/schema/ IR types
internal/generate/typescript TypeScript generator
internal/generate/golang Go generator
internal/version/ Version metadata
License
MIT