ts-yaml
v1.0.0
Published
Add type definitions, code completion, control flow to YAML via TypeScript
Downloads
1,588
Readme
ts-yaml
YAML is awesome!
- Easy to learn.
- Minimal syntax.
But it has some drawbacks, especially as YAML files scale.
- No types/code completion.
- Ambiguous syntax.
- No control flow (e.g. ternary operator, functions,
map).
This is an experiment to define types for YAML in TypeScript, with the goal of easily generating typechecked YAML.
Examples
Buildkite pipleines
Here's a sample pipelines.yml file for Buildkite CI:
steps:
- command: "FIXTURE=cplusplus,schema-cplusplus,kotlin,graphql .buildkite/build-pr.sh"
label: "C++ Kotlin GraphQL"
- command: "FIXTURE=java,schema-java,schema-json-csharp .buildkite/build-pr.sh"
label: "java schema-json-c#"
- command: "FIXTURE=typescript,schema-typescript,javascript,schema-javascript,flow,schema-flow,json-ts-csharp .buildkite/build-pr.sh"
label: "typescript javascript flow"
- command: "FIXTURE=swift,schema-swift,rust,schema-rust,elm,schema-elm .buildkite/build-pr.sh"
label: "swift rust elm"
- command: "FIXTURE=csharp,schema-csharp,ruby,schema-ruby,golang,schema-golang .buildkite/build-pr.sh"
label: "csharp ruby golang"Let's write the type of the YAML in TypeScript. Immediately we have a lot more information than is evident in the YAML sample:
interface Step {
command: string | string[];
label?: string;
branches?: string;
env?: { [name: string]: string };
agents?: { [key: string]: string };
artifact_paths?: string;
parallelism?: number;
concurrency?: number;
concurrency_group?: string;
timeout_in_minutes?: number;
skip?: boolean | string;
retry?:
| { automatic: boolean | AutomaticRetryConditions }
| { manual: boolean | ManualRetryConditions };
}
interface AutomaticRetryConditions {
exit_status?: "*" | number;
limit?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
}
interface ManualRetryConditions {
allowed?: boolean;
reason?: string;
permit_on_pass?: boolean;
}
declare var steps: Step[];Let's make a file named pipeline.yml.ts and define the steps global variable, and we immediately get code completion where we would otherwise have to search Buildkite's docs:

We can finish defining our CI steps:
import "yaml/buildkite";
const fixtures = [
"cplusplus,schema-cplusplus,kotlin,graphql",
"java,schema-java,schema-json-csharp",
"typescript,schema-typescript,javascript,schema-javascript,flow,schema-flow,json-ts-csharp",
"swift,schema-swift,rust,schema-rust,elm,schema-elm",
"csharp,schema-csharp,ruby,schema-ruby,golang,schema-golang"
];
steps = fixtures.map(fixture => ({
command: `FIXTURE=${fixture} .buildkite/build-pr.sh`,
label: fixture
}));Using:
stepsis typechecked- String interpolation
- Data (list of fixtures)
map
Output YAML with ts-yaml pipeline.yaml.ts.
