microsoft / microsoft/TypeScript
[feature request] Support Custom Types for Tagged Template Expressions
Nessuno ha ancora preso questa issue.
- 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
- See if a
taggedTemplateHandlershas been registered for that tag - Call that
taggedTemplateHandlerif one exists. - Use the
TypeNodereturned by thetaggedTemplateHandlerin place of the default behaviour.
- See if a
- When a tagged template is encountered by the type-checker
- 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
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- 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