Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[compiler] Named instantiation of template arguments #2546

Merged
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e12eec0
[compiler] Support named arguments in template instantiation.
willmtemple Oct 5, 2023
96b710c
Some improvements
willmtemple Oct 6, 2023
55259a0
More advanced test cases
willmtemple Oct 6, 2023
df34146
Some final updates
willmtemple Oct 6, 2023
2c18475
Feed linter/cspell
willmtemple Oct 6, 2023
1d419eb
Implement and test semantic colorization, test formatting.
willmtemple Oct 10, 2023
cfce419
rush change
willmtemple Oct 10, 2023
f824689
Update language guide template docs
willmtemple Oct 10, 2023
2d6ccc9
Merge remote-tracking branch 'upstream/main' into compiler/named-temp…
willmtemple Oct 10, 2023
cc72254
Completion, hovers, and improved error recovery
willmtemple Oct 10, 2023
038c6fd
Resolved parameter/argument confusion
witemple-msft Nov 1, 2023
85f794f
Merge remote-tracking branch 'upstream/main' into compiler/named-temp…
witemple-msft Nov 1, 2023
ec7210d
More tests
witemple-msft Nov 1, 2023
6ccabdf
Completion tests
witemple-msft Nov 1, 2023
43a5a8c
Address review feedback
witemple-msft Nov 1, 2023
635288d
Updated a test name
witemple-msft Nov 1, 2023
3f84a08
Merge remote-tracking branch 'upstream/main' into compiler/named-temp…
witemple-msft Nov 1, 2023
20baed5
Added a test for typeref with args as an argument name
witemple-msft Nov 1, 2023
e631621
Removed an unused destructuring binding.
witemple-msft Nov 1, 2023
1b15d38
Merge branch 'main' into compiler/named-template-params
witemple-msft Nov 1, 2023
646ea66
Merge branch 'main' into compiler/named-template-params
markcowl Nov 29, 2023
c03e44f
Update style guide
willmtemple Dec 18, 2023
826ff11
Update packages/compiler/src/formatter/print/printer.ts
witemple-msft Dec 18, 2023
ab97df6
Updated an argument that was renamed
willmtemple Dec 18, 2023
42aab3c
Merge remote-tracking branch 'upstream/main' into compiler/named-temp…
willmtemple Dec 18, 2023
78bc214
a typo
willmtemple Dec 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@typespec/compiler",
"comment": "Added support for named template arguments (#2340)",
"type": "none"
}
],
"packageName": "@typespec/compiler"
}
58 changes: 50 additions & 8 deletions docs/language-basics/templates.md
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also update the naming convention doc to say how to name template param (pascal case without T?)

Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ title: Templates

# Templates

It is often useful to let the users of a model fill in certain details. Templates enable this pattern. Similar to generics found in other languages, model templates declare template parameters that users provide when referencing the type.
It is often useful to let the users of a model fill in certain details. Templates enable this pattern. Similar to generics found in other languages, model templates declare template arguments that users provide when referencing the type.

Templates can be used on:

- [alias](./alias.md)
- [aliases](./alias.md)
- [models](./models.md)
- [operations](./operations.md)
- [interfaces](./interfaces.md)
Expand All @@ -27,7 +27,7 @@ model DogPage {

## Default values

A template parameter can be given a default value with `= <value>`.
A template argument can be given a default value with `= <value>`.

```typespec
model Page<T = string> {
Expand All @@ -36,33 +36,75 @@ model Page<T = string> {
}
```

## Parameter constraints
## Argument constraints

Template parameter can provide a constraint using the `extends` keyword. See [type relations](./type-relations.md) documentation for details on how validation works.
Template arguments can provide a constraint using the `extends` keyword. See the [type relations](./type-relations.md) documentation for details on how validation works.

```typespec
alias Foo<T extends string> = T;
```

now instantiating Foo with the wrong type will result in an error
Now, instantiating Foo with a type that does not satisfy the constraint `string` will result in an error:

```typespec
alias Bar = Foo<123>;
^ Type '123' is not assignable to type 'TypeSpec.string'
```

Template constraints can be a model expression
A template argument constraint can also be a model expression:

```typespec
// Expect T to be a model with property name: string
alias Foo<T extends {name: string}> = T;
```

Template parameter default also need to respect the constraint
Template argument defaults also need to respect the constraint:

```typespec
alias Foo<T extends string = "Abc"> = T
// Invalid
alias Bar<T extends string = 123> = T
^ Type '123' is not assignable to type 'TypeSpec.string'
```

Furthermore, all optional arguments must come at the end of the template. A required argument cannot follow an optional argument:

```typespec
// Invalid
alias Foo<T extends string = "Abc", U> = ...;
^ Required template parameters must not follow optional template parameters
```

## Named template arguments

Template arguments may also be specified by name. In that case, they can be specified out of order and optional arguments may be omitted. This can be useful when dealing with templates that have many defaultable arguments:

```typespec
alias Test<T, U extends numeric = int32, V extends string = "example"> = ...;

// Specify the argument V by name to skip argument U, since U is optional and we
// are okay with its default
alias Example1 = Test<unknown, V = "example1">;

// Even all three arguments can be specified out of order
alias Example2 = Test<
V = "example2",
T = unknown,
U = uint64
>;
```

However, once a template argument is specified by name, all subsequent arguments must also be specified by name:

```typespec
// Invalid
alias Example3 = Test<
V = "example3",
unknown,
^^^^^^^ Positional template arguments cannot follow named arguments in the same argument list.
>;
```

Since template arguments may be specified by name, the names of template arguments are part of the public API of a template. **Changing the name of a template argument may break existing specifications that use the template.**

**Note**: Template arguments are evaluated in the order they are defined in the template _definition_, not the order in which they are written in the template _instance_. Most of the time, this should not matter, but may be important in some cases where evaluating a template argument may invoke decorators with side effects.
Loading