---
title: August 2022
---

This release contains **breaking changes**

- Operation parameters without decorators
- OkResponse is no longer a template
- Route resolution changes
- Remove `Map` type
- `@path` may not decorate optional properties or parameters without a default value

## Operation parameters without decorators

A single undecorated (not marked `@query`, `@header`, `@body` or `@path`) operation parameter will now become a property of the request body rather than have its type define the request body. This allows defining the body with multiple unannotated parameters, which can include unannotated properties that are spread into parameters. (Previously, more than one unannotated parameter was an error.)

For example, the following used to define a request body of type `string`, but now defines a request body that is an object with a property named `body` of type string.

```typespec
op create(body: string): void;
```

To get the previous behavior, the parameter now needs to be explicitly marked with `@body`:

```typespec
op create(@body body: string): void;
```

## OkResponse is no longer a template

Previously, OkResponse took an argument for the body type. Now it is a simple model like the other XxxResponse types. Alone, it implies a status code of 200 with no body.

Since 200 is the default status code for non-empty bodies, you can usually replace `OkResponse<T>` with simply `T`.

```typespec
op get(id: string): OkResponse<Pet>;
```

Can be:

```typespec
op get(id: string): Pet;
```

In certain situations where the body type is not (necessarily) a model, you will need to use the new `Body<T>` type. For example.

```typespec
op list(): OkResponse<Pet[]>;
```

Can become:

```typespec
op list(): OkResponse & Body<Pet[]>;
```

Since 200 status code is used by default, this could also be:

```typespec
op list(): Pet[];
```

Generic models based on `OkResponse<T>` may also require `Body<T>`. For example:

```typespec
model MyResponse<T> {
  ...OkResponse<T>;
  @header example: string;
}
```

Since T is not constrainted to be a model, it might be an intrinsic type, an array, or the like, the template should be changed to use `Body<T>`:

```typespec
model MyResponse<T> {
  ...OkResponse;
  ...Body<T>;
  @header example: string;
}
```

In general, the prior `OkResponse<T>` is equivalent to `OkResponse & Body<T>` now or, equivalently, `{ ...OkResponse, ...Body<T> }`. In practice there are many situations where you can leave out OkResponse altogether and use plain `T` rather than `Body<T>`.

See also https://typespec.io/docs/libraries/http/#request--response-bodies

## Route resolution changes

Resolving operation routes now follows the following logic:

- if there is a service namespace specified
  - only emit the operations and interfaces under that namespace(recursively)
- if not:
  - only emit the operations and interfaces defined at the root (DO NOT look into namespaces)

### Action if applicable

- If a TypeSpec spec used a service namespace without `@serviceTitle` add the `@serviceTitle` decorator to the service namespace, otherwise no routes will be emitted.
- If a TypeSpec spec contains service namespaces that are not child namespaces of the service namespace, move these namespaces under the service namespace.

### Cases

#### Operation at the root

```typespec
op test(): void;
```

✅ Stay the same

| Before  | After   |
| ------- | ------- |
| `["/"]` | `["/"]` |

#### Operation in namespace (not service namespace)

```typespec
namespace DemoService;

op test(): void;
```

⚠️ Output stays the same but add warning that no routes are emitted

| Before | After |
| ------ | ----- |
| `[]`   | `[]`  |

#### Operation in namespace (not service namespace) with @route

```typespec
namespace DemoService;

@route("/")
op test(): void;
```

⚠️ Now the same as previous case, no routes emitted and emit warning

| Before  | After |
| ------- | ----- |
| `["/"]` | `[]`  |

##### Resolve by adding the `@serviceTitle` decorator

Add `@serviceTitle` to the namespace

```typespec
@serviceTitle("DemoService")
namespace DemoService;

@route("/")
op test(): void;
```

#### Operation in service namespace

```typespec
@serviceTitle("My Service")
namespace Foo;

op test(): void;
```

✅ Stay the same

| Before  | After   |
| ------- | ------- |
| `["/"]` | `["/"]` |

#### Operation in namespaces other than the service namespace

```typespec
import "@typespec/rest";

using Http;

@serviceTitle("My Service")
namespace Foo {
  @route("in-service")
  op test(): void;
}

namespace MyLib {
  @route("my-lib")
  op test(): void;
}
```

⚠️ Other namespace routes are not included anymore

| Before                      | After             |
| --------------------------- | ----------------- |
| `["/in-service", "my-lib"]` | `["/in-service"]` |

##### Resolve by making additional namespaces children of the service namespace

Make any added namespaces children of the service namespace

```typespec
import "@typespec/rest";

using Http;

@serviceTitle("My Service")
namespace Foo {
  @route("in-service")
  op test(): void;
}

namespace Foo.MyLib {
  @route("my-lib")
  op test(): void;
}
```

## Remove Map type

`Map` type was removed. Usages of `Map<string, T>` can be replaced with new type `Record<T>`. Other usages of `Map` may be replaced with `object`.

### Map using string key type

```typespec
model Foo {
  options: Map<string, string>;
}
```

#### Replace with `Record<T>`

```typespec
model Foo {
  options: Record<string>;
}
```

### Map using non-string key type

```typespec
model Foo {
  options: Map<int32, string>;
}
```

#### Replace with `object`

```typespec
model Foo {
  options: object;
}
```

## `@path` may not decorate optional properties or parameters without a default

Properties and parameters marked with the `@path` decorator should be required, but may be optional if they have a default value

### optional path parameters

```typespec
model Foo {
  @path
  name?: string;
}
```

Was a bad practice, but was allowed in previous versions. This will now throw an error diagnostic.

### Resolve by making the property required

```typespec
model Foo {
  @path
  name: string;
}
```

### Resolve by adding a default value

```typespec
model Foo {
  @path
  name?: string = "singleton";
}
```
