microsoft / microsoft/typespec

Calling functions in template instantiations

Open
#521 5 comments 0 reactions 0 assignees View on GitHub
design:needed
Dominant language
Java
Stars
5.9k
Forks
394
Avg merge
1d 23h
Merged PRs (30d)
104

Description

See https://github.com/microsoft/cadl/issues/462

Here we have a problem that KeysOf and ParentKeysOf are distinct types that we process twice. It would be nice if we could write:

```
alias ParentKeysOf = KeysOf>
```

However, we don't have currently have a way to author `Parent`. We have a JS function exported `getParentResource` but we don't have a way to call it. It would be nice if we somehow could.

# Brainstormed options

### 1. Allow calling exported functions in type references.

```
alias ParentKeysOf = KeysOf
```

This seems very powerful, but I have some concerns:

* **Tooling**: I once had a bug where I offered all exported functions in type reference completion and it got quite cluttered:

![image](https://user-images.githubusercontent.com/75470/167503173-f1fb547e-d6f6-402b-8a97-89ae64af247d.png)

* **Caching**: I think it would be nice if we could cache these calls in the same way that template instantiations are cached so that you can do complex computation only once for a given set of type arguments.

### 2. Allow calling exported functions using template instantiation syntax

```
alias ParentKeysOf = KeysOf>
```

Here the `< >` parses this as a template instantiation, and when we resolve `getParentResource` to a function, we call it with the type arguments, and cache it like any other template instantiation. This solves the caching, but not the completion noise.

### 3. Explicit template to function bridge

```
alias Parent is getParentResource(T);
```

I struggled with the syntax here so consider this a straw-man. I want something that is different than `alias =`. I first had `model is` but realized it would be useful if this could return a non-model, and then realized it really is equivalent to a templated alias! But if we use `alias =` we are really back to (1). The idea here is that you can make a 1:1 between an alias and a function. So I landed at `alias is` but I don't like it.

But syntax aside this solves the intellisense pollution and allows for idiomatic type (Pascal cased, noun) and function (camel case, verb) names.

### 4. Explicit opt-in of functions as templates
```js
export function $$Parent(program: Program, type: Type) {
return getParentResource(program, type);
}
```

Here we borrow from decorators and have some way to opt a function into becoming a template on the Cadl side. Straw man: `$` is a decorator `$$` is a template. This also solves the intellisense pollution. It could further allow one fewer declaration if you imagine having `getParentResource` implementation inlined into `$$Parent`.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.