Skip to content

0.57 - June 2024

Values In TypeSpec

Decorators often expect some sort of configuration to be passed as an argument. In version 0.51.0 we introduced the valueof keyword to constrain a decorator or template parameter to be a value, however this was limited to string, numeric and boolean values. When dealing with more complex decorators or free form data, one had to use a model type to represent the data. Unfortunately, this approach was difficult for decorator authors to handle reliably and required somewhat sophisticated validation to avoid some common pitfalls that couldn’t be prevented through type system constraints.

In this release we introduce a new concept to TypeSpec: values. This includes new syntax for declaring object and array values, scalar constructors, and const declarations.

Object values

Object values can be declared with the #{} syntax.

const user = #{ name: "Bob", age: 48, address: #{ city: "London" } };

Array values

Array values can be declared with the #[] syntax.

const users = #["Bob", "Frank"];

const

Const declares a variable that holds a value, and can optionally specify a type.

const name = "Bob";
const name: string = "Bob";

Scalar constructors

Scalars can define custom values with scalar value constructors. Scalars which don’t extend a base type like string, number or boolean can define a constructor.

scalar ipV4 {
init fromInt(value: int32);
}
const ip: ipV4 = ipV4.fromInt(3232235776);

See values doc for more info

Breaking changes

  • #3022 Addition of new const keyword means using const as a property name or decorator name will result in an error. This can be fixed by wrapping the property in backtick.
model Test {
// error
const: string;
// correct
`const`: string;
}

Deprecations

@typespec/compiler

  • #3022 Using a tuple type as a value is deprecated. Tuple types in contexts where values are expected must be updated to be array values instead. A codefix is provided to automatically convert tuple types into array values.
model Test {
// Deprecated
values: string[] = ["a", "b", "c"];
// Correct
values: string[] = #["a", "b", "c"];
}
  • #3022 Using a model type as a value is deprecated. Model types in contexts where values are expected must be updated to be object values instead. A codefix is provided to automatically convert model types into object values.
model Test {
// Deprecated
user: {
name: string;
} = {
name: "System";
};
// Correct
user: {
name: string;
} = #{ name: "System" };
}
  • #3022 Decorator API: Legacy marshalling logic

With the introduction of values, the decorator marshalling behavior has changed in some cases. This behavior is opt-in by setting the valueMarshalling package flag to "new", but will be the default behavior in future versions. It is strongly recommended to adopt this new behavior as soon as possible.

Example:

extern dec multipleOf(target: numeric | Reflection.ModelProperty, value: valueof numeric);

Will now emit a deprecated warning because value is of type valueof string which would marshall to Numeric under the new logic but as number previously.

To opt-in you can add the following to your library js/ts files.

export const $flags = definePackageFlags({
decoratorArgMarshalling: "new",
});

Features

@typespec/compiler

  • #3280 Support completion for Model with extended properties

    Example

    model Device {
    name: string;
    description: string;
    }
    model Phone extends Device {
    ┆
    } | [name]
    | [description]
  • #3280 Support completion for object values and model expression properties.

    Example

    model User {
    name: string;
    age: int32;
    address: string;
    }
    const user: User = #{name: "Bob", ┆}
    | [age]
    | [address]
  • #3375 Allow @ to be escaped in doc comment with \

  • #3022 Add syntax for declaring values. See docs.

Object and array values

@dummy(#{
name: "John",
age: 48,
address: #{ city: "London" }
aliases: #["Bob", "Frank"]
})

Scalar constructors

scalar utcDateTime {
init fromISO(value: string);
}
model DateRange {
minDate: utcDateTime = utcDateTime.fromISO("2024-02-15T18:36:03Z");
}
  • #3527 Add support for @prop doc comment tag to describe model properties
  • #3460 Hide deprecated items from completion list
  • #3462 Linter all rulesets is automatically created if not explicitly provided
  • #3533 More logs and traces are added for diagnostic and troubleshooting in TypeSpec language server
  • #3422 Formatter: Indent or dedent multiline strings to the current indentation

@typespec/http

  • #3342 Add new multipart handling. Using @multipartBody with HttpPart<Type, Options>. See multipart docs for more information.

    op upload(
    @header contentType: "multipart/mixed",
    @multipartBody body: {
    name: HttpPart<string>;
    avatar: HttpPart<bytes>[];
    },
    ): void;
  • #3462 Use new compiler automatic all ruleset instead of explicitly provided one

@typespec/openapi3

  • #3022 Add support for new object and array values as default values (e.g. decimals: decimal[] = #[123, 456.7];)

@typespec/html-program-viewer

  • #3022 Add support for values

@typespec/json-schema

  • #3557 Add support for @oneOf decorator.

typespec-vs

typespec-vscode

  • #3533 Enhance logging and trace
  1. Support “Developer: Set Log Level
” command to filter logs in TypeSpec output channel
  2. Add “typespecLanguageServer.trace.server” config for whether and how to send the traces from TypeSpec language server to client. (It still depends on client to decide whether to show these traces based on the configured Log Level.)
  3. More logs and traces are added for diagnostic and troubleshooting
  • #3385 Add ‘TypeSpec: Show Output Channel’ command in VSCode extension

Bug Fixes

@typespec/compiler

  • #3399 Preserve leading whitespace in fenced blocks in doc comments
  • #3522 Fix EINVAL error when running tsp code install
  • #3371 Numeric not handling trailing zeros and causing freeze(e.g. const a = 100.0)
  • #3451 Emitter framework: fix losing context when referencing circular types
  • #3517 Fix application of @param doc tag on operation create with op is to override upstream doc
  • #3488 Add PickProperties type to dynamically select a subset of a model

@typespec/http

  • #3022 Update Flow Template to make use of the new array values

@typespec/versioning

  • #3292 Add @madeRequired decorator
  • #3022 Update to support new value types
  • #3409 Using @removed on member types and @added on containing type could result in errors
  • #3255 If a property were marked with @added on a later version, the logic that said it was originally added on the first version was erroneously removed, resulting in incorrect projections.

@typespec/rest

  • #3022 Update types to support new values in TypeSpec

@typespec/openapi3

  • #3342 Add support for new multipart constructs in http library
  • #3574 Emit diagnostic when an invalid type is used as a property instead of crashing.

@typespec/protobuf

  • #3022 Update to support new value types
  • #3561 Corrected cross-package reference behavior in some buggy cases.

@typespec/json-schema

  • #3398 Fix decorators application for union variants
  • #3022 Update to support new value types
  • #3430 The emitted JSON Schema now doesn’t make root schemas for TypeSpec types which do not have the @jsonSchema decorator or are contained in a namespace with that decorator. Instead, such schemas are put into the $defs of any root schema which references them, and are referenced using JSON Pointers.