tc39 / proposal-string-cooked

ECMAScript proposal for String.cooked built-in template tag

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Function signature bikeshed

jamiebuilds opened this issue · comments

Splitting this conversation off from #1 since I think it might generate a fair bit of conversation.

I'm going to use TypeScript syntax in other to describe the function signatures, along with the TemplateStringsArray type defined in TypeScript:

interface TemplateStringsArray extends ReadonlyArray<string> {
  readonly raw: readonly string[];
}

I'm going to make a couple assumptions from the motivation of this proposal:

  • String.cooked as the direct tag of a tagged template is not useful. (Update: People do find this useful)
  • String.cooked will primarily be used to implement other tag functions. (Update: This is probably still true)

Tag signature

declare function cooked(strings: TemplateStringsArray, ...values: any[]): string;
  • Pro: Familiar signature, probably the same signature as its surrounding method.
  • Neutral: Potentially encourages use of String.cooked as a tag directly, even though thats probably not useful.
  • Pro: Can be used directly as a tag
  • Con: Kind of a confusing signature on its own, unlike most things in JS (outside of tagged templates)

Two-arrays signature

declare function cooked(strings: TemplateStringsArray, values: any[]): string;
  • Pro: More typical signature in JS outside of tagged templates.
  • Neutral: Make using String.cooked as a tag impossible, discouraging potential incorrect usage.
  • Con: Makes using String.cooked directly as a tag impossible
  • Con: Likely different signature from its surrounding method (which is probably a tag)

Other signatures

Feel free to suggest other signatures, please include any pros / cons.

I think being able to use it as a direct tag is quite useful. Imagine an API like:

function doSomething(tag = String.cooked) {
  return tag`special string ${}`;
}

obviously all of that is super contrived, but hopefully it illustrates the utility of having an "identity" tag function that can be used as a default value when no other tag is provided.

While I personally have only had the need for this in the delegation cases, the syntactic tag case is actually what specifically led me to write something up: seeing someone advising folks to alias String.raw as html for tagging HTML strings to take advantage of tooling (highlighters, Prettier processing) that handles tagged-templates-where-the-tag-is-named-html specially (i.e., not lit-html or something but just regular strings.)

I'd encountered this practice once before and it seemed like if multiple people have stumbled on this "solution" - both times not aware of its consequences for escape sequences - then it's a bit of a footgun as-is for raw to stand up there all alone. It's understandable why folks don't realize what raw does precisely because there is no counterpart to contrast it with: "oh, I found the default tag!"

I wouldn't expect a feature to be designed around concerns like "I want to give my editor a signal about how to highlight this", but I think those examples hint at particular dev intuitions which would be better served by a "real" tag.

Okay, I was under wrong impression then. I'll update the issue

Strongly on the "tag signature" bandwagon, for the reasons already given. In particular, if the name cooked is chosen, the obvious and strong parallel with raw would make it very confusing if it had a different signature.

I'd prefer the two-arrays signature. The "identity" use case makes no sense in most cases - it's better to use just a literal, for the "cooked" use case, arrays should be changed, so makes no sense to accept a tag - it's an additional load on the call stack and the spread operator can be just forgotten.

it's an additional load on the call stack and the spread operator can be just forgotten.

I don't think it is particularly meaningful overhead that it should be specifically designed to prevent anyone from ever using it that way. And I don't think we should make things different for the sake of making them different.