Map types (also known as dictionaries) allow you to store key-value pairs. Most of BAML’s syntax (clients, tests, classes) is represented as maps.
Syntax
A mapping from keys to values
map<string, string> // String keys to string values
map<string, int> // String keys to integer values
map<Category, Person> // Enum keys to class values
map<"A" | "B", string> // Literal string keys to values
Basic Map Declaration
Maps use a simple key-value syntax without colons:
{
key1 value1,
key2 {
nestedKey1 nestedValue1,
nestedKey2 nestedValue2
}
}
Key Points:
- No colons between keys and values (space-separated)
- Values can be unquoted strings, quoted strings, booleans, numbers, or nested maps
- Classes in BAML are represented as maps
Simple Map Example
class Person {
name string
age int
isEmployed bool
}
function DescribePerson(person: Person) -> string {
client "openai/gpt-4o-mini"
prompt #"
Describe the person with the following details: {{ person }}.
"#
}
test PersonDescription {
functions [DescribePerson]
args {
person {
name "John Doe",
age 30,
isEmployed true
}
}
}
Generated Types
from typing import Dict
# When used as map<string, string>
data: Dict[str, str] = {
"name": "John Doe",
"occupation": "Engineer"
}
Nested Maps
Maps can contain nested map structures:
class Company {
name string
location map<string, string>
employeeCount int
}
function DescribeCompany(company: Company) -> string {
client "openai/gpt-4o-mini"
prompt #"
Describe the company with the following details: {{ company }}.
"#
}
test CompanyDescription {
functions [DescribeCompany]
args {
company {
name "TechCorp",
location {
city "San Francisco",
state "California"
},
employeeCount 500
}
}
}
Generated Types
from typing import Dict
from baml_client.types import Company
company = Company(
name="TechCorp",
location={
"city": "San Francisco",
"state": "California"
},
employeeCount=500
)
Enum Keys
Maps can use enums as keys:
enum Category {
A
B
C
}
class CategoryData {
scores map<Category, int>
}
function AnalyzeScores(data: CategoryData) -> string {
client "openai/gpt-4o-mini"
prompt #"
Analyze these category scores: {{ data.scores }}
"#
}
test ScoreAnalysis {
functions [AnalyzeScores]
args {
data {
scores {
A 95,
B 87,
C 92
}
}
}
}
Generated Types
from typing import Dict
from enum import StrEnum
class Category(StrEnum):
A = "A"
B = "B"
C = "C"
scores: Dict[Category, int] = {
Category.A: 95,
Category.B: 87,
Category.C: 92
}
Literal String Keys
Use literal string unions for fixed key sets:
class Config {
settings map<"development" | "staging" | "production", string>
}
test ConfigTest {
functions [ProcessConfig]
args {
config {
settings {
development "localhost:3000",
staging "stage.example.com",
production "example.com"
}
}
}
}
Generated Types
from typing import Dict, Literal
Environment = Literal["development", "staging", "production"]
settings: Dict[Environment, str] = {
"development": "localhost:3000",
"staging": "stage.example.com",
"production": "example.com"
}
Maps with Complex Values
class Project {
title string
description string
}
class Team {
projects map<string, Project>
}
function DescribeTeam(team: Team) -> string {
client "openai/gpt-4o-mini"
prompt #"
Describe this team's projects: {{ team.projects }}
"#
}
test TeamDescription {
functions [DescribeTeam]
args {
team {
projects {
alpha {
title "Project Alpha",
description "First initiative"
},
beta {
title "Project Beta",
description "Second initiative"
}
}
}
}
}
Generated Types
from typing import Dict
from baml_client.types import Project, Team
team = Team(
projects={
"alpha": Project(
title="Project Alpha",
description="First initiative"
),
"beta": Project(
title="Project Beta",
description="Second initiative"
)
}
)
Maps with Multiline Strings
class Project {
title string
description string
}
function DescribeProject(project: Project) -> string {
client "openai/gpt-4o-mini"
prompt #"
Describe the project with the following details: {{ project }}.
"#
}
test ProjectDescription {
functions [DescribeProject]
args {
project {
title "AI Research",
description #"
This project focuses on developing
advanced AI algorithms to improve
machine learning capabilities.
"#
}
}
}
TypeScript Map vs Record
map<string, ValueType> generates a Record<string, ValueType> in TypeScript.Other key types (enums, literals) generate a Map<KeyType, ValueType>.
// Generates Record in TypeScript
map<string, string>
// Generates Map in TypeScript
map<Category, string>
map<"A" | "B", string>
Optional Maps
class Config {
metadata map<string, string>?
}
function ProcessConfig(config: Config) -> string {
client "openai/gpt-4o-mini"
prompt #"
{% if config.metadata %}
Metadata: {{ config.metadata }}
{% else %}
No metadata provided.
{% endif %}
"#
}
Generated Types
from typing import Dict, Optional
metadata: Optional[Dict[str, str]] = None
# or
metadata: Optional[Dict[str, str]] = {"key": "value"}
Best Practices
- Use string keys for flexible, dynamic data structures
- Use enum keys when you have a fixed set of known keys
- Use literal string unions for configuration with known environments/modes
- Nest maps carefully - deep nesting can make debugging harder
- Consider classes instead of maps when structure is well-defined