Configuration
The TypeSpec compiler and libraries can be configured either via a configuration-file or command line flags.
Configuration file
Section titled “Configuration file”TypeSpec configuration can be provided via the tspconfig.yaml configuration file.
Project Configuration
Section titled “Project Configuration”A tspconfig.yaml file can be marked as a project configuration by setting kind: project at the top level:
kind: projectentrypoint: main.tspemit: - "@typespec/openapi3"A project configuration marks a project boundary — it serves the same role as package.json does today for boundary detection, but is specific to TypeSpec. When the compiler or IDE encounters a tspconfig.yaml with kind: project, it treats that directory as the root of a TypeSpec project.
Set to "project" to mark the directory as a TypeSpec project root.
Constraints:
kind: projectcan only be used in files namedtspconfig.yaml. Custom-named config files (e.g. used with--config) cannot be project configs.
entrypoint
Section titled “entrypoint”Declares the main TypeSpec file for the project. This is used by both the CLI (tsp compile <dir>) and the IDE (language server) to determine which file to compile.
- Default:
main.tsp(whenkind: projectis set but noentrypointis specified) - Can only be used when
kind: projectis set.
kind: projectentrypoint: src/service.tspEntrypoint Resolution Priority
Section titled “Entrypoint Resolution Priority”When compiling a directory, the compiler resolves the entrypoint in this order:
- Project tspconfig — If the directory has a
tspconfig.yamlwithkind: project, use itsentrypoint(defaults tomain.tsp) - package.json
tspMain— If apackage.jsonexists with atspMainfield, use that main.tsp— Fall back tomain.tspin the directory
The IDE language server uses the same priority when walking up directories to find the project root for a given TypeSpec file. When a project boundary (kind: project) is found, the walk stops — files outside the project boundary are not considered.
Discovery
Section titled “Discovery”The TypeSpec compiler will look for the closest tspconfig.yaml file located in the same directory or closest parent directory from the TypeSpec entrypoint.
For example if running tsp compile /dev/foo/bar/main.tsp, the compiler will lookup the file at the folllowing paths (in order):
/dev/foo/bar/tspconfig.yaml/dev/foo/tspconfig.yaml/dev/tspconfig.yaml/tspconfig.yaml
Schema
Section titled “Schema”The file is a yaml document with the following structure. See the next section for details on each option.
model TypeSpecProjectSchema { kind?: "project"; entrypoint?: string; extends?: string; parameters?: Record<{default: string}>; `environment-variables`?: Record<{default: string}>; `warn-as-error`?: boolean; `output-dir`?: string; `trace`?: string | string[]; imports?: string[]; emit?: string[]; `dry-run`?: boolean; options?: Record<unknown>; linter?: LinterConfig;}
model LinterConfig { extends?: RuleSetRef[]; enable?: Record<RuleRef, boolean | object>; disable?: Record<RuleRef, string>;}Extending Project Files
Section titled “Extending Project Files”There may be instances where you want to build different folders with varying options (such as different emitters), but still want to share some common configurations.
In such cases, you can use the extends property in the configuration file.
For instance, in <my-pkg>/tspconfig.yaml:
options: emitter1: some-option: my-name emitter2: some-other-option: This is a titlein <my-pkg>/proj2/tspconfig.yaml, enable emitter1 using the options specified in the parent tspconfig.yaml
extends: ../tspconfig.yamlemit: - emitter1What gets extended
Section titled “What gets extended”The extending logic follows these rules:
- Root-level properties: Shallow merge for all properties except
options - Options property: Deep merge at one level (per emitter)
- Override behavior: Properties specified in the extending file will completely override those from the extended file
Root-level merge behavior:
When extending a configuration, most properties (like emit, imports, trace, etc.) are merged at the root level. If the same property exists in both files, the extending file’s value completely replaces the extended file’s value.
Options merge behavior:
The options property receives special treatment with a one-level deep merge:
- Different emitters from both files are combined
- If the same emitter is configured in both files, the extending file’s emitter configuration completely overrides the extended file’s configuration for that emitter
- Individual emitter options are not merged - it’s all or nothing per emitter
Example:
# Base config (parent/tspconfig.yaml)emit: - emitter1options: emitter1: option-a: value-a option-b: value-b emitter2: option-x: value-x
# Extending config (child/tspconfig.yaml)extends: ../tspconfig.yamlemit: - emitter3 # Completely replaces the emit arrayoptions: emitter1: # Completely replaces emitter1 options option-c: value-c emitter3: # Added alongside emitter2 from parent option-y: value-y
# Resulting merged config:# emit: [emitter3] # Only emitter3, emitter1 is gone# options:# emitter1: { option-c: value-c } # Only option-c, option-a and option-b are gone# emitter2: { option-x: value-x } # Inherited from parent# emitter3: { option-y: value-y } # From extending configVariable interpolation
Section titled “Variable interpolation”The TypeSpec project file provides variable interpolation using:
- built-in variables
- environment variables
- config file parameters
- emitter options can reference each other
Variable interpolation is done using an variable expression surrounded by { and }. ({<expression>})
Examples:
{output-dir}/my-path{env.SHARED_PATH}/my-path
Interpolation of Emitter Path Config
Section titled “Interpolation of Emitter Path Config”Certain emitter configurations can be interpolated using a specific rule designed to collapse a path.
If a variable is succeeded by a / or . and the emitter responsible for interpolating the config doesn’t supply that variable, the path segment will be omitted.
For instance, consider the following config value: {service-name}/output.{version}.json
Here’s what would be produced:
| Service name value | Version value | Result |
|---|---|---|
"PetStore" | "v1" | PetStore/output.v1.json |
"PetStore" | undefined | PetStore/output.json |
Built-in variables
Section titled “Built-in variables”| Variable name | Scope | Description |
|---|---|---|
cwd | * | Points to the current working directory |
project-root | * | Points to the the tspconfig.yaml file containing folder. |
output-dir | emitter options | Common output-dir See output-dir |
emitter-name | emitter options | Name of the emitter |
service-name | service name | Name of the service |
service-name-if-multiple | service name if multiple | Name of the service if multiple, undefined if one |
Project Parameters
Section titled “Project Parameters”A TypeSpec project file can define certain parameters that can subsequently be specified through the CLI.
Parameters can be organized in a nested structure, to access different levels of the structure, use dots (.) in the variable expression.
Therefore, parameter names should not contain . in their name.
The {cwd} and {project-root} variables can be utilized in the default value of these parameters.
These parameters can then be referred to by their name in a variable interpolation expression.
All parameters must have a default value. Example:
parameters: base-dir: default: "{cwd}"
output-dir: {base-dir}/outputThe parameter can then be specified via --arg in this format --arg "<parameter-name>=<value>" and for nested structures --arg "<parameter-name>.<nested-parameter-name>=<value>"
tsp compile . --arg "base-dir=/path/to/base"Environment variables
Section titled “Environment variables”A TypeSpec project file can specify which environment variables it can interpolate.
The {cwd} and {project-root} variables can be used in the default value of these environment variables.
These environment variables can then be referred to by their name in a variable interpolation expression, using the env. prefix.
All environment variables must have a default value.
Example:
environment-variables: BASE_DIR: default: "{cwd}"
output-dir: {env.BASE_DIR}/outputEmitter Options
Section titled “Emitter Options”Emitter options can refer to each other by using the other option’s name as the variable expression.
Interpolation is only possible among emitter options from the same emitter.
options: @typespec/openapi3: emitter-output-dir: {output-dir}/{emitter-sub-folder} emitter-sub-folder: barEmitter options support a nested structure, enabling complex configurations.
options: emitter-sub-folder: sub-folder: barTo set these values via the CLI, use dots to navigate deeper levels in the definition. --option "<option-name>.<nested-option-name>=<value>"
Due to this capability, emitter option names should not contain a . in their name.
TypeSpec Configuration Options
Section titled “TypeSpec Configuration Options”| Config | Cli | Description |
|---|---|---|
kind | Set to "project" to mark as a project boundary | |
entrypoint | Main TypeSpec file (requires kind: project) | |
output-dir | --output-dir | Default output directory |
config | --config | Path to config file or folder to search for config file. |
trace | --trace | Specify tracing area to enable |
warn-as-error | --warn-as-error | Treat warning as error |
imports | --import | Additional imports to include |
emit | --emit | Emitter configuration |
options | --option or --options | Emitter configuration |
dry-run | --dry-run | Tell emitters to run in dryRun mode |
linter | Linter configuration |
output-dir - Configure the default output dir
Section titled “output-dir - Configure the default output dir”Specify the common output-dir for all emitters. See this to configure per emitter.
output-dir: {cwd}/typespec-buildOutput dir can be provided using the --output-dir cli flag
tsp compile . --output-dir "./typespec-build"Output dir must be an absolute path in the config. Use {cwd} or {project-root} to explicitly specify what it should be relative to.
See output directory configuration for mode details
trace - Configure what to trace
Section titled “trace - Configure what to trace”Configure what area to trace. See tracing docs
# Trace all.trace: *
# or specific areastrace: - import-resolution - projectionTrace can be provided using the --trace cli flag
tsp compile . --trace import-resolution --trace projectionwarn-as-error - Treating Warnings as Errors
Section titled “warn-as-error - Treating Warnings as Errors”All warnings will be treated and emitted as errors, resulting in a non-zero exit code in the event of a warning.
It is recommended to use this feature in Continuous Integration (CI) to ensure all warnings are addressed.
warn-as-error: trueor via the cli
tsp compile . --warn-as-error--ignore-deprecated
Section titled “--ignore-deprecated”Suppress all deprecated diagnostics that are raised when declarations are marked with the #deprecated directive.
tsp compile . --ignore-deprecatedimports - Configure additional imports
Section titled “imports - Configure additional imports”imports: - sidecar.tspSpecify additional TypeSpec files to import
tsp compile . --import "sidecar.tsp"emit - Specifying which emitters to run
Section titled “emit - Specifying which emitters to run”Specify which emitters to use and their options if applicable.
The value can be the name of an emitter or a path to the emitter package/entrypoint.
emit: - emitter1 # Package name - /path/to/emitter2 # Give a path to an emitteror via the cli
tsp compile . --emit emitter1 --emit /path/to/emitter2options - Configuring emitters
Section titled “options - Configuring emitters”Emitters can define a set of options, those can be set as the value of the map.
options: # Enable and configure emitter1 emitter1: option1: "option1-value" option2: "option1-value" # Only enable emitter2 emitter2: trueEmitters options can also be provided using the --option in this format --option=<emitterName>.<optionName>=<value>
tsp compile . --option "emitter1.option1=option1-value"Options specified via the CLI take precedence over the ones specified in tspconfig.yaml.
Emitters built-in options
Section titled “Emitters built-in options”emitter-output-dir
Section titled “emitter-output-dir”Represent the path where the emitter should be outputing the generated files.
Default: {output-dir}/{emitter-name}
See output directory configuration for mode details
linter - Setting Up Linters
Section titled “linter - Setting Up Linters”This allows you to configure the linter rules to be enabled in this repository. When referencing a rule or ruleset, use their ID, which follows the format <libraryName>/<ruleName>.
linter: extends: # Extend `recommended` ruleset from @typespec/best-practices library - "@typespec/best-practices/recommended"
enable: # Explicitly enable some rules "@typespec/best-practices/no-x": true
disable: # Disable some rules defined in one of the ruleset extended. "@typespec/best-practices/no-y": "This rule cannot be applied in this project because X"You can also reference rules and rulesets using their short name, where the package scope is stripped (@typespec/<name> → <name>, @<scope>/typespec-<name> → <name>) or replaced by a library-declared alias. The library must be loaded (imported) for its short name to be resolved. The full name is always accepted.
linter: extends: - "best-practices/recommended" enable: "best-practices/no-x": trueIf two loaded libraries would resolve to the same short name, that short name is ambiguous: using it reports a warning and the entry is skipped, so the full name must be used for those libraries.
Configuring rule options
Section titled “Configuring rule options”Some rules accept options to customize their behavior. To pass options, use an object instead of true when enabling the rule:
linter: enable: # Enable with default options "@typespec/my-linter/required-doc": true
# Enable with custom options "@typespec/my-linter/naming-convention": style: "PascalCase" allowUnderscores: falseWhen an object is provided, the values are merged with the rule’s default options. See each rule’s documentation for available options.
Extending a ruleset defined in a file
Section titled “Extending a ruleset defined in a file”A ruleset can also be defined in a standalone YAML file and referenced with the file: prefix. This is useful to share a common set of rules across multiple projects, or to version a ruleset independently of the libraries providing the rules.
linter: extends: - "file:../common-rules.yaml"The referenced file has the same shape as the linter config:
extends: - "@typespec/best-practices/recommended" - "@typespec/http/recommended"enable: "@typespec/best-practices/new-rule": truedisable: "@typespec/best-practices/foo": "This rule is too strict for this repository"Relative paths are resolved relative to the file declaring them: a file: reference in tspconfig.yaml resolves relative to the config file, and a file: reference inside a ruleset file resolves relative to that ruleset file. Ruleset files may extend other ruleset files, and rulesets defined in libraries, in any combination.
file: references can only be used in tspconfig.yaml or in another ruleset file. A ruleset defined in a library cannot use them, as it is not anchored to any directory the path could be resolved against.
CLI Flags for Emitter Control
Section titled “CLI Flags for Emitter Control”--no-emit
Section titled “--no-emit”This flag disables emitters. Emitters will not run, and no files will be emitted.
This flag can also be used to suppress the “There are no emitters” warning.
tsp compile . --no-emit--dry-run
Section titled “--dry-run”This flag tells compatible emitters to run in dry-run mode. In this mode, emitters will not emit any files, but will still run and log diagnostics.
tsp compile . --dry-runOther Command line flags
Section titled “Other Command line flags”--config
Section titled “--config”Specify a different config file for build overrides.
tsp compile . --config ./tspconfig.alt.yaml--watch
Section titled “--watch”Start the tsp compiler in watch mode: watch for file changes and compile on save.
tsp compile . --watch--nostdlib
Section titled “--nostdlib”Don’t load the TypeSpec standard library.
tsp compile . --nostdlib--version
Section titled “--version”Log the version of the tsp compiler.
tsp compile . --version--pretty
Section titled “--pretty”Default: true
Enable/Disable pretty logging (colors, diagnostic preview, etc.).
tsp compile . --pretty=falseConfiguring Output Directory
Section titled “Configuring Output Directory”The TypeSpec compiler assigns a unique output directory to each emitter that runs, in order to minimize conflicts. By default, the output directory of an emitter is set to:
{output-dir}/{emitter-name}where:
output-diris the common output directory for the compiler, which can be configured via--output-dir.emitter-nameis the name of the emitter package (for example,/openapi3).
For instance, if the emitters @typespec/openapi3 and @typespec/jsonschema are given, the default output folder structure would be:
Directory{project-root}/tsp-output
Directory@typespec:
Directoryopenapi3
- … openapi3 files …
Directoryjsonschema
- … json schema files …
You can change the compiler’s output-dir with --output-dir or by setting that value in the tspconfig.yaml, which would result in the following structure:
--output-dir={cwd}/my-custom-output-dirDirectory{cwd}/my-custom-output-dir
Directory@typespec:
Directoryopenapi3
- … openapi3 files …
Directoryjsonschema
- … json schema files …
To change a specific emitter’s output directory, you can set the emitter-output-dir option for that emitter:
--option "@typespec/openapi3.emitter-output-dir={project-root}/openapispec"Directory{project-root}
Directoryopenapispec
- … openapi3 files …
Directorytsp-output
Directory@typespec
Directoryjsonschema
- … json schema files …