microsoft / microsoft/TypeScript

[feature request] Support Custom Types for Tagged Template Expressions

Offen
#16,551 7 Kommentare 23 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

In Discussion Suggestion
Vorherrschende Sprache
Go
Sterne
111k
Forks
14.4k
Ø Merge
1 T. 19 Std.
Gemergte PRs (30 T.)
117

Beschreibung

Problem Statement

It is common to embed queries in tagged template expressions within typescript. For example, you might use sql:

const result = await querySQL(sql`SELECT * FROM users WHERE id = ${userID}`);

You also see a similar pattern with graphql:

const result = await queryGraph(graphql`query { user { id, name } }`);

Currently, there is no way to provide type information about what is returned by queryGraph/querySQL. A lot of potential type information is lost at the boundary here.

I obviously don't expect typescript to read the graphql or SQL schema, as that's way out of scope. What I would like is a way to provide this information as a module author.

Proposal

I believe that all that's needed is a way to write plugins that answer the question "given a tagged template expression, what type does it return". This would only affect the type checker. It would not change generated code or add any new syntax.

A new compilerConfig option called taggedTemplateHandlers would be added, that would take an array of paths to typescript files. An example might look something like:

import {parseSqlQuery, convertSqlTypeToTypeScriptType} from 'sql-helpers';
import * as ts_module from "typescript/lib/tsserverlibrary";

export default {
  tag: 'sql',
  templateHandler(modules: {typescript: typeof ts_module}, strings: string[], ...expressions: Array<ts_module.Expression>) {
    const ts = modules.typescript;

    const fields = parseSqlQuery(strings.join('"EXPRESSION"'));
    return ts.createTypeReferenceNode(
      ts.createIdentifier('SqlQuery'), // typeName
      ts.createNodeArray([ // typeArguments
        ts.createTypeLiteralNode(Object.keys(fields).map(field => {
          return ts.createPropertySignature(
            ts.createIdentifier(field),
            undefined, // question token
            convertSqlTypeToTypeScriptType(fields[field]), // type
            undefined, // initializer
          )
        }))
      ])
    );
  }
};

You could then define querySQL like:

define function querySQL<TResult>(query: SqlQuery<TResult>): Promise<TResult>;

Language Feature Checklist

  • Syntactic - no new changes
  • Semantic
    • When a tagged template is encountered by the type-checker
      1. See if a taggedTemplateHandlers has been registered for that tag
      2. Call that taggedTemplateHandler if one exists.
      3. Use the TypeNode returned by the taggedTemplateHandler in place of the default behaviour.
  • Emit - no new changes
  • Compatibility - no new syntax is added/changed, so it should be fully backwards/forwards compatible.
  • Other
    • I expect there will be some performance impact, but hopefully the fact that both plugins and the compiler are written in typescript should make this minimal.
    • Ideally, this information would be used for autocomplete helpers as well as in the typechecker, I do not know if that would require extra work.

I'm happy to do my best to help implement this, but I would need some pointers on where to start.

P.S. would it be possible to pass in the type of the expressions, in place of the actual expressions themselves?

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Das Issue nennt keine Dateien, Tests oder Einstiegspunkte. Beginne damit, die Typprüfung von tagged-template und die Verarbeitung von compilerConfig zu lokalisieren, und ermittle anschließend, wie ein handler einen Rückgabetyp bereitstellen könnte, ohne emit zu beeinflussen; als abgeschlossen gilt die Implementierung und das Testen des vorgeschlagenen Konfigurations- und type-checker-Verhaltens.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
typescript
Bereich
compilers
Issue-Typ
Feature
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
25/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.