microsoft / microsoft/TypeScript

Design Meeting Notes, 2026-07-23

Abierto
#63,676 0 comentarios 2 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Design Notes
Lenguaje dominante
Go
Estrellas
111k
Forks
14.3k
Merge medio
2 d 4 h
PR fusionados (30 d)
132

Descripción

JavaScript Emit API

https://github.com/microsoft/typescript-go/pull/4699

  • How would something like "compile on save" be reimplemented?
    • Idea: LSP has didSave event, clients can listen and trigger a custom emit command
    • Does emit in LSP make sense?
    • We do expect it for the playground.
    • Sounds like yes.
  • Source maps?
    • Should add those too.
  • What's the (internal) API look like?
    • program.emit(emitOnly?: EmitOnly) - file system (including VFS if supplied), whole program, respects emit-blocking options like noEmit, noEmitOnError, ...

      • Some weirdness in interaction, e.g. emitDeclarationOnly
    • program.emitToString(emitOnly?: EmitOnly) - in-memory string results, whole program, respects emit-blocking options

      • Basically a string over IPC
    • program.getJavaScriptEmit(files?: readonly DocumentIdentifier[]) - in-memory string results, specific file selection, bypasses emit-blocking options

      • In-memory, does not respect noEmit, emitDeclarationOnly, etc.
    • program.getDeclarationEmit(files?: readonly DocumentIdentifier[]) - (same)

    • And EmitOnly is:

      export enum EmitOnly {
          All = 0,
          OnlyJs = 1,
          OnlyDts = 2,
      }
      
  • May have to consider how pre/post transformations work here, plus dynamically contributed content - recall that Angular might have been looking for this with ngc?

Content Mappers

// tsconfig.json
{
    "compilerOptions": {
        // ...
    },
    "contentMappers": [
        {
            "package": "vue-content-mapper",
            "extensions": [".vue"],
        }
    ],
    "include": ["src"]
}
// node_modules/vue-content-mapper/package.json
{
    "name": "vue-content-mapper",
    "version": "1.0.0",
    "tsContentMapper": {
        "exec": ["node", "dist/server.js"],
        "compilerOptions": ["module", "jsx", "jsxImportSource"]
    }
}
  • What kind of versioning contract can we provide here?
    • Stuff like LSP/Language Server Protocol doesn't provide a version per se - it's all capabilities based. Looks like same with AHP/Agent Host Protocol.
      • Can keep version, but stick close to that model.
  • Why does this have to be a protocol instead of something like a potentially long-running process? Feels heavy.
    • Don't want to have multiple invocations of the mapper.
    • Cascading resolution: we don't always know which files the program itself includes (you can end up with .vue files outside of the program)
    • Also, we have long-running things like --watch and LSP where the program state will change over time.
    • These transforms are all supposed to be idempotent.
  • One issue is: are these able to react to their configurations, and invalidate their resolution?
    • We can react to the package itself changing, but not currently to configuration.
    • Maybe we need something about config files that the plugin can watch.
  • Do we allow this only for --moduleResolution bundler or for --moduleResolution nodenext and others?
    • It works across everything.
  • Top-level contentMappers field - how does this work with tsconfig inheritance?
    • It currently doesn't.
  • This does have some invasiveness in our LSP implementation.
    • Two different spans in a .ts file can map to the same span in a .vue file.
      • Also, want these operations to coalesce occasionally.
    • So operations at Line X Column Y now potentially have multiple results!
      • So some operations default to the first result (hover), some concatenate results (go-to-definition).
  • This doesn't completely subsume Volar - Volar can mask/fix up errors.
    • But you can build an LSP over this to do this if desired.
  • What are examples of that funky LSP behavior?
    • Take for example:
      <script setup lang="ts">
      import { ref, computed } from "vue";
      
      const count = ref(0); const label = ref("clicks");
      const label = computed(() => count.value === 1 ? "click" : "clicks");
      const doubled = computed(() => count.value *2);
      
      function increment(): void {
        count.value++;
      }
      </script>
      
      <template>
        <div class="counter">
          <p>{{ count }} {{ label }}</p>
          <p>doubled = {{ doubled }}</p>
          <button @click="increment()">+1</button>
          <ul>
            <li v-for="(n, i) in [count, doubled]" :key="i">{{ n }}</li>
          </ul>
          <span v-if="count > 5">high</span>
        </div>
      </template>
      
    • Kinda remaps to...
      // SCRIPT SETUP START:
      
      export default createComponent({
        // ...
        setup(props) {
      
      // VERBATIM-ISH SCRIPT BLOCK:
        const count = ref(0);
        // ...
      
      // GENERATED AFTER SCRIPT:
        return {
          count,
        };
      });
      
      // GENERATED FROM TEMPLATE BLOCK:
      
      function render(props)
        const { count } = props;
      
        // usage of count
        count;
      }
      
    • A reference to count in the <template> block has a definition that doesn't exist in the original .vue source, but also has a mapping to have a mapping back to a node that is not the "true" definition site.

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Este es un registro de una reunión de diseño, no una tarea de implementación, y no menciona archivos fuente ni pruebas. Empieza leyendo las pull requests enlazadas 4699 y 4712 y el comentario de issue de TypeScript referenciado. Para darlo por terminado, sería necesario acordar una API de emisión de JavaScript y el alcance del protocolo content-mapper antes de poder definir el trabajo de implementación.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
javascript, typescript
Área
compilers, devtools
Tipo de issue
Nueva funcionalidad
Dificultad
5/5
Tiempo estimado
Más de una semana
Estado de actividad
Tranquilo
Claridad
Necesita aclaración
Aptitud para principiantes
25/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.