microsoft / microsoft/TypeScript

[feature request] Support Custom Types for Tagged Template Expressions

Aperta
#16,551 7 commenti 23 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

In Discussion Suggestion
Lingua principale
Go
Stelle
111k
Fork
14.3k
Merge medio
1g 19h
PR unite (30g)
117

Descrizione

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?

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

L’issue non indica file, test o punti di ingresso. Inizia individuando il controllo dei tipi di tagged-template e la gestione di compilerConfig, quindi determina come un handler potrebbe fornire un tipo restituito senza influire su emit; il lavoro sarebbe completo implementando e testando il comportamento proposto di configurazione e del type-checker.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
typescript
Ambito
compilers
Tipo di issue
Funzionalità
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
25/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.