Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

Type after `as` or `satisfies` at end of line is tokenized as an expression

Abierto
#1,079 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
68/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
typescript
Área
tooling

Línea de trabajo

Start with TypeScript.YAML-tmLanguage around lines 1755-1761 and line 62, then run repro.mjs with the listed vscode-textmate and vscode-oniguruma versions. Compare scopes for the inline and multiline as and satisfies examples; done means the next-line type receives the same type scopes without breaking the semicolonless single-line case.

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

Descripción

When a line ends with as or satisfies, the type on the next line gets expression scopes instead of type scopes.

JavaScript and TypeScript Nightly version: not tested in the extension. Reproduced with TypeScript.tmLanguage at eeeb0dc4daa8793b8227bb3b34ddfc267c85fd81 (current master), vscode-textmate 9.3.2, vscode-oniguruma 2.0.1, Node 26.7.0, macOS arm64.

Code

const a = b as A | undefined

const a = b as
  A | undefined

const a = b satisfies
  A | undefined

Prettier 3.9.8 emits this layout when an as expression exceeds the print width, e.g.:

const inlineSourceMap = convertSourceMap.fromSource(content)?.toObject() as
  SourceMap | undefined

Actual

Token Same line Next line
A entity.name.type.ts variable.other.constant.ts
| keyword.operator.type.ts keyword.operator.bitwise.ts
undefined support.type.builtin.ts constant.language.undefined.ts

A type on the line after satisfies gets the same scopes as a type on the line after as.

Expected

The same scopes on both layouts, because TypeScript parses both as a type assertion with the type A | undefined.

Repro script
npm install [email protected] [email protected]
curl -sLO https://raw.githubusercontent.com/microsoft/TypeScript-TmLanguage/eeeb0dc4daa8793b8227bb3b34ddfc267c85fd81/TypeScript.tmLanguage
node repro.mjs
// repro.mjs
import { readFileSync } from "node:fs";
import { createRequire } from "node:module";
import vsctm from "vscode-textmate";
import oniguruma from "vscode-oniguruma";

const require = createRequire(import.meta.url);
await oniguruma.loadWASM(
  readFileSync(require.resolve("vscode-oniguruma/release/onig.wasm")).buffer,
);
const registry = new vsctm.Registry({
  onigLib: Promise.resolve({
    createOnigScanner: (patterns) => new oniguruma.OnigScanner(patterns),
    createOnigString: (s) => new oniguruma.OnigString(s),
  }),
  loadGrammar: async () =>
    vsctm.parseRawGrammar(
      readFileSync("TypeScript.tmLanguage", "utf8"),
      "TypeScript.tmLanguage",
    ),
});
const grammar = await registry.loadGrammar("source.ts");

const tokenize = (code) => {
  let state = vsctm.INITIAL;
  for (const line of code.split("\n")) {
    const { tokens, ruleStack } = grammar.tokenizeLine(line, state);
    state = ruleStack;
    for (const { startIndex, endIndex, scopes } of tokens) {
      const text = line.slice(startIndex, endIndex);
      if (text.trim())
        console.log(JSON.stringify(text).padEnd(10), scopes.at(-1));
    }
  }
  console.log();
};

tokenize("const a = b as A | undefined");
tokenize("const a = b as\n  A | undefined");
tokenize("const a = b satisfies\n  A | undefined");

Possible cause (unverified)

The as/satisfies rule's end includes $ through lookAheadEndOfType, so the type ends at the line break right after the keyword:

https://github.com/microsoft/TypeScript-TmLanguage/blob/eeeb0dc4daa8793b8227bb3b34ddfc267c85fd81/TypeScript.YAML-tmLanguage#L1755-L1761
https://github.com/microsoft/TypeScript-TmLanguage/blob/eeeb0dc4daa8793b8227bb3b34ddfc267c85fd81/TypeScript.YAML-tmLanguage#L62

The $ is presumably what ends the type at the end of a line without a semicolon (x as T followed by a new statement), so dropping it could break that case.

Lenguaje dominante
TypeScript
Estrellas
471
Forks
150
Métricas de merge de PR
Sin PR fusionados en 30 d

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

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.

Más de microsoft/TypeScript-TmLanguage

Todos los issues de microsoft/TypeScript-TmLanguage

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.