Typescript: Compatibilidad con complementos para transformadores personalizados

Creado en 2 mar. 2017  ·  99Comentarios  ·  Fuente: microsoft/TypeScript

Desde que llegó #13764, es fácil escribir transformadores personalizados. Sin embargo, si entiendo la API correctamente, es necesario duplicar toda la línea de comando tsc solo para agregar un solo transformador. Esto conduce a incompatibilidades ya que estas aplicaciones, según el mecanografiado, no admiten las mismas funciones que la herramienta de línea de comandos tsc.

Por lo tanto, sería preferible tener un sistema de complementos que permita cargar transformadores personalizados desde módulos de nodos de terceros, como es el caso de los proxies de servicios de idiomas #12231. Estos transformadores luego se integran fácilmente en las herramientas de compilación/flujos de trabajo de compilación existentes.

Si alguien con experiencia tiene aportes sobre cómo implementar los cambios, estoy dispuesto a crear un PR, ya que simplificaría enormemente mi proyecto.

Docs

Comentario más útil

No quiero tener una API de complemento expuesta. En cambio, preferiría registrar mis transformaciones personalizadas simplemente especificándolas en tsconfig.json en lugar de tener que usar la API de TS-Compiler. Porque el uso de la API de TS-Compiler implica que ya no puedo usar la herramienta de línea de comandos tsc, lo que además puede implicar que ya no se integra bien en las herramientas de compilación y los flujos de trabajo existentes.

Todos 99 comentarios

No planeamos exponer el sistema de complementos del compilador a corto plazo. Las transformaciones se exponen como parte de la API pública, como notó, y estamos en el proceso de escribir documentación y muestras para estos.

No quiero tener una API de complemento expuesta. En cambio, preferiría registrar mis transformaciones personalizadas simplemente especificándolas en tsconfig.json en lugar de tener que usar la API de TS-Compiler. Porque el uso de la API de TS-Compiler implica que ya no puedo usar la herramienta de línea de comandos tsc, lo que además puede implicar que ya no se integra bien en las herramientas de compilación y los flujos de trabajo existentes.

¿Alguna actualización sobre la documentación y las muestras? @mhegazy

@MichaReiser puede escribir un compilador simple basado en la API (muestra aquí ). De hecho, usamos mucho TS dentro de Yahoo Finance y la API pública del transformador ha sido increíble.

Estos son algunos de los transformadores que escribimos después de que se hizo público:
https://github.com/longlho/ts-transform-system-importación
https://github.com/longlho/ts-transform-img
https://github.com/longlho/ts-transform-react-intl
https://github.com/longlho/ts-transform-css-modules-transform

@mhegazy lmk si necesita ayuda para documentar/recolectar muestras

@longlho
Gracias por tu muestra.

Eso es lo que estoy haciendo actualmente. Sin embargo, hace que sea imposible usar otras herramientas de compilación creadas para mecanografiado, por ejemplo, cargadores de paquetes web, cargadores de bromas. Además, ¿cómo puedo usar uno de sus complementos junto con uno de los míos cuando cada uno de nosotros usa una interfaz diferente?

Por lo tanto, creo que el enfoque actual es un buen comienzo pero no suficiente para un ecosistema de complementos. Porque usar un complemento es demasiado esfuerzo para el usuario y requiere más que solo escribir el código de transformación para el autor.

Creo que un sistema de complementos como el de Babel es esencial para TypeScript si el objetivo es alentar a la comunidad a crear y usar transformadores personalizados.

@MichaReiser sí . No digo que sea suficiente para el ecosistema, solo lo suficientemente bueno para el primer paso hacia él.

Me gustaría agregar soporte para transformaciones en gulp-typescript, pero quiero evitar que todos los complementos de TypeScript (para gulp, webpack, etc.) propongan una API diferente. Y TypeScript podría agregar incluso una forma diferente de configurar esto más adelante. Entonces, ¿actualmente tiene planes para agregar esto en un futuro cercano o lejano?

Hola a todos, trato de escribir un preprocesador, pero no sale nada :[

De hecho, tengo dos preguntas:

  • ¿Cómo crear un fragmento AST a partir de una cadena?
  • ¿Cómo agregar importación?
// 1. Input
class Foo {
    templateString = 'some value';
}

// 2. After transformation
import __LIB__ from '@external/lib';

class Foo {
    templateString = (function compiledTemplate(deps) {
        // ...
        return result;
    })({lib: __LIB__});
}

// 3. Expected result
var lib_1 = require("@external/lib");
var Foo = (function () {
    function Foo() {
        this.templateString = (function compiledTemplate(deps) {
            // ...
            return result;
        })({ lib: lib_1 }); 
    }
    return Foo;
}());

Un ejemplo simplificado: https://github.com/RubaXa/typescript-api-questions/tree/master/import-add

⬆️ ⬆️ ⬆️
@longlho , @mhegazy ¿Puedes darnos alguna pista?

@RubaXa Dado que agregó la declaración de importación en una transformación, no está vinculada ni verificada. Dado que no se vinculó ni se revisó el tipo, no podemos resolver __LIB__ en su expresión a __LIB__ en la declaración.

Una opción es utilizar una importación de espacio de nombres en lugar de una importación predeterminada, de modo que su emisión sea algo así como:

import * as __LIB__ from "@external/lib"

Como no hay aliasing que pueda ocurrir.

El otro conserva un identificador generado para la declaración de importación, según el zip adjunto

@RubaXa si su objetivo es pasar todo el objeto del módulo, probablemente quiera usar la sintaxis import * as __LIB__ from "@external/lib" (que no requiere alias) y no import __LIB__ from "@external/lib" ya que este último importa el default exportar en lugar de todo el objeto del módulo.

sí, también estamos haciendo import * as foo en nuestro transformador de módulos CSS para evitar el aliasing. Aunque sería bueno aprovechar eso para incorporar ciertas exportaciones con nombre

@rbuckton O, ¡muchas gracias!
¿Todavía está interesado en cómo crear un fragmento AST arbitrario a partir de una cadena?

function createFragmentFromString(code: string) {
  // ????
}

function visitPropertyDeclaration(node) {
    if (ts.isIdentifier(node.name) && node.name.text === "templateString") {
        // ...
        return ts.updateProperty(
            node,
            ts.visitNodes(node.decorators, visitor),
            ts.visitNodes(node.modifiers, visitor),
            ts.visitNode(node.name, visitor),
            ts.visitNode(node.type, visitor),
            createFragmentFromString('(function compiledTemplate() { /* ... */ })()')
        );
    }
    return node;
}

Esto es lo que esperaba que el soporte del transformador y el flujo de trabajo se comportaran como en TypeScript.

https://www.dartlang.org/tools/pub/transformers

También estoy muy interesado en esta característica.

como mencionó @MichaReiser
If someone experienced has inputs on how to implement the changes, I'm willing to create a PR as it would simplify my project tremendously.

Me encanta ver las aportaciones de los expertos/compilador de texto mecanografiado DEV.

Parece que alguien ha envuelto mecanografiado para exponer esta funcionalidad. https://github.com/cevek/ttypescript

También parece que ts-loader lo tiene: https://www.npmjs.com/package/ts-loader#getcustomtransformers -----before-transformerfactory--after-transformerfactory----

Creo que esto es algo que podría aterrizar en el lanzamiento de TypeScript 2.8 o al menos en la hoja de ruta en algún momento, @ahejlsberg @mhegazy @DanielRosenwasser , ¿qué piensas? De esta forma, los transformadores personalizados podrían ser más populares y, por lo tanto, más potentes. Tener la opción de conectar el transformador desde la perspectiva de tsconfig.json simplificaría mucho la vida.

No tenemos planes de exponer complementos a corto plazo, como se señaló anteriormente.

@mhegazy ¿Es una decisión considerada o está fuera del alcance solo por el bajo interés de la comunidad?

Yo no dije eso. nos gustaría mantener un costo de mantenimiento/API público pequeño, así como flexibilidad para cambiar la forma en que se impulsa la compilación, y ambos se ven afectados por un modelo de complemento.

Por favor, detenga la fragmentación de la API del complemento del transformador. Estabilice la API del complemento sobre la API del transformador y expóngalas en tsconfig.json.

ts-loader , paquete-plugin-typescript , rollup-plugin-typescript2 , ts-transformer-keys , ttypescript y otros.

Cada uno de ellos proporciona un método de registro de complemento personalizado y un formato de punto de entrada de complemento personalizado. Es una forma de ts plugin hell.

Ahora cevec/ttypescript es compatible con todos los formatos comunes de complementos de transformadores. Es un envoltorio desplegable sobre todos los módulos TypeScript y los comandos tsc, tsserver (solo un pequeño parche de tiempo de ejecución ts.createProgram). Webpack ts-loader y rollup-plugin-typescript2 se pueden configurar fácilmente con ttypescript.

TTypescript sugiere un formato de complemento de transformador universal, pero los transformadores existentes también son compatibles.

{
    "compilerOptions": {
        "plugins": [
            { "transform": "ts-transform-graphql-tag" },
            { "transform": "ts-transform-css-modules", "type": "config" },
            { "transform": "ts-nameof", "type": "raw", "after": true}
            { "transform": "./transformers/my-transformer.ts", "someOption1": 123, "someOption2": 321  }
        ]
    },
    "exclude": ["node_modules", "transformers/**/*"]
}

¿Alguna noticia sobre este? Me parece que los autores de TypeScript de alguna manera no quieren permitir transformadores personalizados en TypeScript de vainilla; es una pena, sería una característica increíble.

no quieren otra api/superficie para mantener por temor a causar dificultades para romper cosas en el interior. Irónicamente, todas estas soluciones de complementos de terceros son, debido a que no hay un estándar por parte del equipo de ts, todas algo diferentes y eventualmente se romperán.

no quieren otra api/superficie para mantener por temor a causar dificultades para romper cosas en el interior.

Después de 3 años trabajando con mecanografiado y viendo su evolución, he llegado a una conclusión sencilla. Microsoft tiene Typescript de código abierto en el sentido del _código_, pero no en el sentido del _proceso_. En la mayoría de los casos, los proyectos de código abierto están más o menos impulsados ​​por la comunidad tanto en las decisiones como en la codificación , y esta debería ser la forma natural de evolucionar. ¿Recuerdas la bifurcación IO.js de node.js? La comunidad se dio cuenta de que los intereses de la empresa no estaban tan alineados con el modelo común de gobierno de código abierto y simplemente se bifurcaron. Espero que esto no suceda con TypeScript, pero Microsoft debería tener en cuenta esta posibilidad.
Para ser claros, no estoy culpando a los desarrolladores, de todos modos, ellos hacen un gran trabajo, de verdad.
Solo mi 2c, perdón por el OT.

Microsoft tiene Typescript de código abierto en el sentido del código, pero no en el sentido del proceso.

Estoy totalmente en desacuerdo con esto. Nunca trabajé para Microsoft, pero tuve una influencia directa en varias funciones de TypeScript durante los últimos 4 años. Estaba representando una biblioteca de código abierto construida en TypeScript, y acordamos tener algunas conversaciones directas, pero todo el "debate" de cualquier función se realizó aquí, en público. El equipo central publica sus notas de la reunión de diseño. La única "información privilegiada" que obtuve, en representación de una biblioteca de código abierto, fue una oportunidad para defender mi caso en persona para algunas funciones y conocer al equipo central. Me hizo darme cuenta de que el equipo actúa como un equipo. Una característica de la que hablamos, Anders básicamente dijo que el problema era demasiado difícil y que tomaría mucho tiempo eliminarlo y resolver los problemas "reales" que enfrentaba la gente. Eso fue hace dos años y en TypeScript 3.0 finalmente lo conseguimos. Pero la comunidad tiene una voz en el proceso de diseño, pero como cualquier comunidad, tenemos varias voces, y ningún equipo en ningún lugar podría complacer a todos, y si lo hicieran, TypeScript sería una herramienta _realmente_ mala.

También desea etiquetar el equipo central como "Microsoft". El equipo central fue el equipo menos Microsoft que he conocido. Pelearon batallas para obtener el control total de la cadencia de su lanzamiento, después de que se basaron en el control total del contenido de su lanzamiento. También lucharon por la apertura y la transparencia. Lucharon por pasar a GitHub desde CodePlex. Es cierto que ya no son tan únicos en Microsoft ya que varios otros equipos han adoptado su modelo, pero fueron, hasta donde yo sé, los que comenzaron todo, seguidos rápidamente por el equipo de VSCode.

Entonces, el hecho de que el equipo central elija y elija sus batallas, se apegue a sus Principios de diseño no significa que la comunidad no tenga voz, pero como voz sufrimos un trastorno psicótico de personalidad múltiple. Somos un cliente difícil de atender.

Tengo entendido que esto es lo mismo que # 16607, ¿o lograría un objetivo diferente? Como autor de complementos muy reciente, también me gustaría ver esto expuesto, incluso cuando se trabaja con TypeScript usando el complemento Babel.

@mrmckeb , este problema es para estandarizar y exponer la transformación AST mecanografiada, que ya existe, mientras que el problema vinculado parece estar discutiendo la transformación de archivos completos en un alcance muy amplio (indefinido).

Quiero agregar mis 2 centavos aquí. Algunos de ustedes pueden haber oído hablar del brillante proyecto babel-plugin-macros . Básicamente, en lugar de tener miles de complementos de Babel diferentes, puede haber uno solo que funcione con un código de usuario para realizar una transformación. Un sistema asombrosamente transparente sin necesidad de meterse con la configuración todo el tiempo. Esto es especialmente bueno para proyectos como CRA que admite macros pero prohíbe la configuración adicional.

Hoy abrí la discusión sobre cómo llevar esto al mundo de TypeScript. Si tienes alguna idea, por favor ven y comparte.

En última instancia, espero que si de alguna manera tenemos éxito, no habrá necesidad de esto, ya que solo será necesaria una transformación.

@FredyC es un proyecto genial, pero necesitaríamos que este problema se resolviera para inyectar fácilmente algo así en el compilador cuando solo se usa tsc . Por ejemplo, con babel-plugin-macros aún debe especificarse en .babelrc y sería bueno especificar algo así en mecanografiado en tsconfig.json .

En realidad, ¿está sugiriendo que sería bueno tener un comportamiento similar al del complemento babel-macro integrado en TypeScript y que no sería necesaria ninguna configuración? Eso podría ser bueno, pero personalmente preferiría una solución configurable que permita especificar transformadores personalizados en tsconfig.json y luego se podría especificar una versión de babel-plugin-macros que admita nodos ast mecanografiados.

@dsherret Sí, no espero que sea parte de TypeScript. Sin embargo, puedo imaginar que una vez que la transformación esté lista, podría ser fácil preparar un contenedor pequeño similar a tsc que inyectaría solo esa transformación para macros y el resto se podría hacer desde un código de usuario.

Editar: en realidad, el pequeño envoltorio ya está allí, con https://github.com/cevek/ttypescript mencionado anteriormente, sería fácil instruirlo para usarlo junto con el complemento de macros universal y es beneficioso para todos.

Solo necesito encontrar personas que estén bien versadas en transformaciones mecanografiadas para calcular algún prototipo básico. Puedo discutir y hablar, pero implementarlo está por encima de mi conjunto de habilidades actual.

no quieren otra api/superficie para mantener por temor a causar dificultades para romper cosas en el interior.

Después de 3 años trabajando con mecanografiado y viendo su evolución, he llegado a una conclusión sencilla. Microsoft tiene Typescript de código abierto en el sentido del _código_, pero no en el sentido del _proceso_. En la mayoría de los casos, los proyectos de código abierto están más o menos impulsados ​​por la comunidad tanto en las _decisiones_ como en la _codificación_, y esta debería ser la forma natural de evolucionar. ¿Recuerdas la bifurcación IO.js de node.js? La comunidad se dio cuenta de que los intereses de la empresa no estaban tan alineados con el modelo común de gobierno de código abierto y simplemente se bifurcaron. Espero que esto no suceda con TypeScript, pero Microsoft debería tener en cuenta esta posibilidad.
Para ser claros, no estoy culpando a los desarrolladores, de todos modos, ellos hacen un gran trabajo, de verdad.
Solo mi 2c, perdón por el OT.

Estoy de acuerdo. Está claro que, a pesar del gran interés de la comunidad, los desarrolladores simplemente rechazan la idea de los transformadores/macros personalizados sin proporcionar una razón para el rechazo, excepto algo como "La gente lo usará indebidamente", lo que también suena ofensivo para la comunidad. como implica, es una comunidad de desarrolladores de baja calidad.

Aceptaría un rechazo si se pudiera proporcionar una justificación razonable que no sea "No lo haremos simplemente", pero parece que, a pesar de todas las solicitudes de la comunidad, nadie se ha esforzado aún por proporcionar eso.

Creo que esta es una crítica injusta @pietrovismara. Estoy de acuerdo en que esta es una función imprescindible, pero no es "Microsoft" la que bloquea esta función. Según tengo entendido, el equipo dice que esto no es fácil de admitir y es por eso que aún no han agregado esa función.

Una vez más, quiero esta característica tanto como cualquier otra persona, pero debemos discutir este problema usando hechos. Los hechos son que el equipo aún no está listo para apoyarlo. Así que sigamos expresando interés, pero también mantengamos la conversación en el camino correcto.

@mrmckeb Si ese es el caso, puedo entenderlo. Debo haber perdido tal declaración en la gran cantidad de comentarios contenidos en estos números en ese momento. No pretendía ofender a nadie, solo intentaba provocar una respuesta clara de los mantenedores para, como dijiste, mantener la conversación en el camino correcto.

Está bien, es frustrante que el soporte para esto no exista; como dije, lo siento, y se nos pide algún tipo de solución para los módulos CSS todo el tiempo en CRA ahora que tenemos soporte para TypeScript. Espero que llegue pronto, pero también entiendo que abre una gran área de riesgo para el equipo.

... todavía esperando :(

sí, todavía esperando ..., pero esperando qué, ¿se ha hecho algo?

¿Hay alguna solución mejor que ttypescript ahora?
¿Los desarrolladores de TypeScript finalmente planean admitir complementos?

Puedes crear tu propio compilador ;-)

¿Alguna novedad sobre el tema? Me parece que la comunidad ha hecho uso de esta función lo suficientemente extensa como para sentarse, recopilar comentarios y finalmente agregar soporte para transformadores al archivo de configuración. Incluso hay muchas implementaciones para usar como referencia.

Han pasado más de 2 años (¡guau!)*. ¿La gente está abierta a repensar los pros y los contras de abrir complementos para transformadores?

Siento que las preocupaciones iniciales que existían hace tanto tiempo, como la falta de documentación sobre la API y tener que admitir la malla de código de usuario <-> transformadores <-> API, ya no son tan relevantes. La compatibilidad con complementos abiertos ha funcionado de maravilla para paquetes como babel: progresión a través de la colaboración. Puedo dar fe personalmente de Babel específicamente, habiéndolo usado extensamente.

Una integración más fácil de "simplemente funciona" de transformadores como TypeScript -is _sería_ agradable. Veo que este paquete en particular tiene una influencia revolucionaria en el mecanografiado en su conjunto. ¡Contratos verdaderamente fuertes! 😃

Creo que una conversación sobre los pros y los contras ayudaría a disipar cualquier abatimiento o diferencias al respecto. Tengo la sensación de que este problema de zombis continuará hasta que suceda, para ser honesto.

* Y mientras tanto, alguien crea la función para TS en su lugar ( ttypescript ). He usado esto para el éxito.

@DanielRosenwasser Vi que había "Investigar las API del complemento TypeScript" en el plan de iteración 3.5 (y ese trabajo ya comenzó).
¿Ese punto se ocupa de lo que se discute en este número? La falta de un enlace a un problema me hace suponer que es demasiado WIP para compartir algo al respecto todavía.

Creo que se debe trabajar para agregar soporte completo para el analizador de Babel, que incluye agregar las funciones necesarias para que Babel admita el análisis estático de TypeScript (por ejemplo, transformaciones de archivos múltiples o dependencia de archivos múltiples durante la transformación). En lugar de tener que duplicar la sintaxis/transformar los complementos de Babel en equivalentes de TypeScript.

en caso de que tenga algún problema con las siguientes instrucciones, hágamelo saber, con gusto lo ayudaré

dada la pura negligencia del equipo de diseño, aquí hay una solución

vamos a aprovechar tslint y sus capacidades de corrección de código

en el siguiente ejemplo vamos a hacer una transformación de tipo a código , en su forma más básica

vamos a usar decoradores como marcadores de lugares en el código que necesitan ser reescritos

en nuestro caso, un decorador es una función falsa cuyo único objetivo es

  • para marcar un lugar de la transformación
  • y capturar el tipo que va a ser la fuente de información para el generador

para fines de demostración, vamos a volcar los nombres y tipos de propiedades de una interfaz como cadenas simples, en una clase subyacente

Los siguientes pasos son solo para usuarios de Windows, si no eres uno de ellos, que Dios te ayude:

  1. inicia tu código VSC
  2. instale la siguiente extensión: https://github.com/Microsoft/vscode-typescript-tslint-plugin
  3. cierra tu código VSC
  4. ir a una carpeta de su elección
  5. ejecutar git clone https://github.com/zpdDG4gta8XKpMCd/code-gen.git
  6. ve a la carpeta code-gen : cd ./code-gen
  7. correr

    • 1-install.bat

    • 2-build.bat

    • 3-install-some-more.bat

    • 4-try.bat

  8. observar una instancia de VSCode abierta
  9. ir a test.ts ( Ctrl + P -> test.ts )
  10. tome nota de la siguiente interfaz, será la fuente para el generador de código
interface Data {
    one: string;
    another: number;
}
  1. tome nota de la siguiente función, que consta de un decorador fantasma que vamos a utilizar como marcador
function gen<_T>() {
    return function (meh: any) {};
}
  1. tome nota del sitio de reescritura, donde queremos insertar un código de generación automática basado en la interfaz y el decorador de marcadores
@gen<Data>()
export class Gen {
}
  1. observe una línea ondulada debajo de @gen<Data>()
    image

  2. elige Quick fix... -> Needs a rewrite, wanna fix?
    image

  3. observe el código generado automáticamente:
    image


como referencia, aquí está el código fuente del generador que puede encontrar en codeGenRule.ts

import * as Lint from 'tslint';
import * as ts from 'typescript';

export class Rule extends Lint.Rules.TypedRule {
    public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
        return this.applyWithWalker(new Walker(sourceFile, this.getOptions(), program.getTypeChecker()));
    }
}

class Walker extends Lint.RuleWalker {
    constructor(sourceFile: ts.SourceFile, options: Lint.IOptions, private checker: ts.TypeChecker) {
        super(sourceFile, options);
    }
    public visitNode(node: ts.Node) {
        if (ts.isDecorator(node)) {
            const checked = check(node, this.checker);
            if (checked !== undefined) {
                const [node, message, replacement] = checked;
                this.addFailureAtNode(node, message, replacement);
            }
        }
        super.visitNode(node);
    }
}

function check(node: ts.Decorator, checker: ts.TypeChecker) {
    const { expression, parent } = node;
    if (!ts.isClassDeclaration(parent)) return;
    if (!ts.isCallExpression(expression)) return;
    const { expression: identifier, typeArguments: typeArgs } = expression;
    if (!ts.isIdentifier(identifier)) return;
    const { text: name } = identifier;
    if (name !== 'gen') return;
    if (typeArgs === undefined) return;
    if (typeArgs.length > 1) return;
    if (typeArgs.length < 1) return;
    const [only] = typeArgs;
    const type = checker.getTypeFromTypeNode(only);

    // if you got to here, you are at the right place and you have a type

    // working on a fix
    const properties = checker.getPropertiesOfType(type);
    const allNameTypes = properties.map(p => {
        const { name } = p
        const type = checker.getTypeOfSymbolAtLocation(p, node);
        return name + ': \'' + checker.typeToString(type) + '\';'
    })
    const { newLine } = ts.sys;
    const body = newLine + allNameTypes.join(newLine);
    const { pos: start, end } = parent.members;
    return [
        node,
        'Needs a rewrite, wanna fix?',
        Lint.Replacement.replaceFromTo(start, end, body)
    ] as const;
}

@zpdDG4gta8XKpMCd , gracias por compartir su concepto, pero sea cortés.

dada la pura negligencia del equipo de diseño, aquí hay una solución

Esta no es la forma adecuada de abordar el TypeScript por no implementar una _característica_ que a usted (y a muchos otros, incluyéndome a mí) le gustaría tener. Esto no es un defecto importante y no refleja "negligencia". Por favor, sea respetuoso.

oh, por favor, no lo tome como algo personal, esta es la forma en que siempre empiezo mis quejas, tengo una personalidad muy amarga (condición médica) y esto es lo mejor que puedo sacar de mí mismo, lo siento mucho

ustedes no van a dejar de sorprenderme

  • lo que ve es una pieza de código que parece capaz de resolver un problema importante de hoy con comodidad (sin trucos, sin piratería)
  • esta solución alternativa es una llamada de atención para el equipo de diseño y, como vimos antes, cuando la comunidad estaba a punto de dar un giro en la dirección equivocada, el equipo de diseño estuvo allí para solucionarlo de inmediato: #4212,
  • así que si les importa, pueden hacerlo bien antes hasta que sea demasiado tarde, o si no les importa, somos libres de cavar en esta dirección y no será un problema para ellos en el futuro.
  • así que el tono de mi comentario fue algo inapropiado, pero todo el tono apropiado tuyo no te ha servido de nada desde el 2 de marzo de 2017 (más de 2 años), y sí, puedes esperar otros 2 años.

@zpdDG4gta8XKpMCd ¿Qué ha contribuido a una implementación real? TypeScript es de código abierto; No tengo ninguna duda de que considerarían seriamente una solicitud de extracción si creara una (incluso parcialmente).

Culpar de su mala educación a una condición médica es inaceptable; son palabras que escribiste y voluntariamente elegiste hacer clic en "comentar". Ninguna condición médica te obliga a hacer eso. Hablar, tal vez, no escribir. También ha tenido la oportunidad de editar su comentario para eliminarlo, pero no lo ha hecho.

Si necesita transformadores personalizados _ahora_, puede usar Babel. Puede eliminar anotaciones de tipo de casi todos los TypeScript, al tiempo que permite transformaciones de sintaxis tan fácilmente como desee. Como beneficio adicional, también es más rápido.

Le sugiero que deje de comentar antes de que lo expulsen del repositorio de Microsoft de forma permanente. Sé que si fuera mi repositorio, estarías en tu última gota.

ok, me echaste, entonces que
¿Puedo volver alguna vez? ¿puedo crear una nueva cuenta?
¿Crees que me importa demasiado esta cuenta?

de todos modos, sí, probé solicitudes de extracción, desafortunadamente no es factible por las siguientes razones:

  1. hay una cierta categoría de problemas que puede resolver, que son bastante triviales y de menor interés, cualquier cosa seria como esta, y usted no está

  2. dado que no puede resolverlo por su cuenta, un problema como este (incluso teniendo 224 pulgares arriba) puede esperar años si alguna vez se considera en absoluto

  3. afortunadamente puedes hacer algo hoy usando cualquier medio que tengas y empezar a hacer una diferencia que se puede ver, de ahí la sugerencia (no me culpes por no hacer nada)

@zpdDG4gta8XKpMCd Por mucho que sepas, he sido fanático de las tomas cínicas a lo largo de los años, tengo que estar de acuerdo con otros aquí: debemos mantener una conversación civilizada y respetuosa. Siempre es bueno recordar que todos los que siguen este problema quieren mejorar el proyecto .


@Janpot Sí, es en gran medida un WIP, aunque cuando @rbuckton regrese, es posible que pueda brindar más detalles sobre el estado.

A medida que investigamos los puntos de los complementos (como mencioné en el plan de iteración 3.5), creo que exponer ganchos más fáciles para los transformadores personalizados es un escenario importante que queremos considerar. La razón por la que no necesariamente haríamos esto directamente es que podríamos tener un trabajo más amplio que subsume esto. En otras palabras, tal vez haya algo más amplio que los transformadores previos y posteriores.

@DanielRosenwasser no hay mucho de cínico en eso, solo dije 2 palabras y luego dije que lo siento mucho por eso

de todos modos, el punto es que creo que todos estamos de acuerdo en que hay una buena parte de una sana frustración sobre cómo van las cosas, y no te culpamos, entendemos lo que impulsa este proyecto.

pero si lo miramos desde nuestro punto de vista, debe haber alguien a quien culpar, porque dejar que temas como este se queden durante años simplemente recogiendo los pulgares hacia arriba, es lo que hace que dejemos de ser más productivos.

Estoy seguro de que hay razones para posponerlo y centrarse en otras cosas primero, así que creo que sería mejor si le hicieras saber a tu audiencia por qué no se pueden cumplir ciertas funciones muy deseadas, podría reducir el grado de frustración, por ejemplo:

  • no podemos implementar esta función debido a A, BC y esos necesitan D, E y F hechos primero

así que supongo que me refiero a esta conversación: https://github.com/Microsoft/TypeScript/issues/30696#issuecomment -478799258

Tener el visto bueno no crea nuevos recursos de la nada, hace que las decisiones complejas y difíciles sean simples y fáciles, cambia las prioridades comerciales existentes, detiene los proyectos en curso, resta prioridad a otros trabajos, hace que las propuestas demasiado ambiciosas se vuelvan bien definidas o alterar una sugerencia con impactos permanentes y de gran alcance para que sea enfocada y mantenible.

No me disculpo por hacer (o permitir relaciones públicas para , que es de lo que se quejaba en el n.º 30696) un trabajo bueno y simple bien entendido por adelantado antes de un trabajo extremadamente complejo y de alto mantenimiento como este. No debería ser difícil adivinar por qué estamos dispuestos a dejar que alguien entre y arregle un grifo que gotea mientras los planes para remodelar el sótano y agregar otro piso en la parte superior de la casa aún se están resolviendo.

@zpdDG4gta8XKpMCd ¿Por qué necesitarías culpar a alguien? ¿Por qué no te culpas a ti mismo en primer lugar por no haber hecho un PR para solucionar este problema? ¿O al menos algún escrito constructivo sobre cómo abordarlo desde el punto de vista de la implementación?

Oh hombre, incluso después de ese escrito transparente que acabas de vincular, ¿decidiste pinchar al oso nuevamente después de solo 2 semanas? Intenta imaginar estar en esa posición con más de 1500 tareas a mano y tienes que elegir un par de ellas. En nuestro equipo, estamos moviendo alrededor de 100 tareas y luchando bastante. No puedo imaginar que sería 15 veces más 😮

@FredyC por el amor de Dios, mira mi solución antes de decir que no estoy haciendo nada

sí, no estoy haciendo solicitudes de extracción formales porque:

  1. no estoy al nivel para hacer una buena

  2. para los simples, hay una larga línea de aprobación, y se necesita un tremendo trabajo para mantener una solicitud de extracción creada hace 2 años actualizada con el código base actual, no tengo tanto tiempo

  3. ciertos problemas ni siquiera se considerarán, dadas las grandes consideraciones de diseño de las que solo unas pocas personas como anders hejlsberg conocen

no puedes quitarme la parte de la frustración, y no estoy solo aquí

sabemos que hay estos factores en juego:

  • gran diseño del lenguaje
  • presupuesto / recursos / política dentro de MS
  • deseos de la comunidad

sería más feliz si la toma de decisiones con la combinación de estos ingredientes fuera un poco más clara

he terminado, ha ido demasiado lejos, lo siento por todos aquellos cuyos sentimientos fueron heridos, no diré una palabra

continuación de https://github.com/Microsoft/TypeScript/issues/14419#issuecomment -483920640

otra opción es usar las propias declaraciones de función como marcadores, lo que se muestra a continuación es una implementación de un generador de código para funciones cuyos nombres comienzan con toRandom...

la fuente de información para el generador es el tipo de resultado de la función

Así es como funciona:

  1. observe la línea ondulada debajo de una función que comienza con toRandom...
    image
  2. explora tus opciones:
    image
  3. hacer una solución rápida
    image
  4. observa los resultados:
    image

aquí está el código de codeGenRule.ts que lo hace

como beneficio adicional, esta implementación solo generará un problema de pelusa si el código actual de la función no coincide con el código que se supone que debe generarse

import * as Lint from 'tslint';
import * as ts from 'typescript';

export class Rule extends Lint.Rules.TypedRule {
    public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
        return this.applyWithWalker(new Walker(sourceFile, this.getOptions(), program.getTypeChecker()));
    }
}

class Walker extends Lint.RuleWalker {
    constructor(sourceFile: ts.SourceFile, options: Lint.IOptions, private checker: ts.TypeChecker) {
        super(sourceFile, options);
    }
    public visitFunctionDeclaration(node: ts.FunctionDeclaration) {
        const checked = check(node, this.checker);
        if (checked !== undefined) {
            const [node, message, fix] = checked;
            this.addFailureAtNode(node, message, fix);
        }
        super.visitFunctionDeclaration(node);
    }
}

function check(node: ts.FunctionDeclaration, checker: ts.TypeChecker) {
    const { name: identifier, type: result, body } = node;
    if (body === undefined) return;
    if (identifier === undefined) return;
    const { text: name } = identifier;
    if (!name.startsWith('toRandom')) return;
    if (result === undefined) return;
    const type = checker.getTypeFromTypeNode(result);

    // if you got to here, you are at the right place and you have a type

    // working on a fix
    const properties = checker.getPropertiesOfType(type);
    const newerBody =
        `{
    return {${properties.map(prop => {
            const { name } = prop;
            const type = checker.getTypeOfSymbolAtLocation(prop, node);
            const typeName = capitalize(checker.typeToString(type));
            return `
        ${name}: toRandom${typeName}(),`;
        }).join('')}
    };
}`;
    const olderBody = body.getFullText();
    if (areEqual(olderBody, newerBody)) return;
    const start = body.getFullStart();
    const end = start + body.getFullWidth();
    return [
        node,
        'Needs a rewrite, wanna fix?',
        Lint.Replacement.replaceFromTo(start, end, newerBody),
    ] as const;
}

function areEqual(one: string, another: string) {
    // AB: we cannot make any assumption what line endings are,
    // this is why we compare the text of code without them
    return one.replace(/\r\n|\n/g, ' ') === another.replace(/\r\n|\n/g, ' ');
}

export function capitalize(value: string): string {
    const length = value.length;
    if (length > 1) {
        return value.substr(0, 1).toUpperCase() + value.substr(1);
    } else if (length > 0) {
        return value.substr(0, 1).toUpperCase();
    } else {
        return value;
    }
}

@ zpdDG4gta8XKpMCd Creo que este problema se trataba más de tener una forma más fácil de conectar transformadores personalizados mientras se emite. Ex. especificando transformaciones en tsconfig.json para que puedan usarse con tsc en lugar de usar la API . ¿Desea cambios/arreglos de código personalizados en el editor?

No los he usado en absoluto, pero creo que lo que estás hablando ya podría ser posible con un complemento de servicio de idioma (creo que anulando getCodeFixesAtPosition en el servicio de idioma e insertando tus propias acciones de código... aunque no estoy seguro) https://github.com/Microsoft/TypeScript/wiki/Writing-a-Language-Service-Plugin

¿O tal vez estoy malinterpretando?

Correcto. eso es exactamente lo que solía pensar

pensé que una forma de especificar mis transformaciones personalizadas a través tsconfig.json sería un sueño hecho realidad

pero luego me di cuenta de que me gusta aún más mi solución

aquí está mi línea de pensamiento:

  • necesitaba un generador de código configurable enchufable
  • mecanografiado no tiene nada de eso a mano
  • por otro lado, sé que tslint (aunque se depreció a fines de 2019) es una plataforma de complementos decente para mecanografiar que tiene una forma de conectar y configurar su código con gran libertad
  • resulta que tiene todo lo que necesito:

    • enchufable y configurable

    • con toda la interfaz de usuario necesaria

    • me da una API para mecanografiar

    • tiene algunos pequeños extras

Dado todo eso, no puedo verme escribiendo algo que use el servicio de lenguaje mecanografiado, porque:

  • mi computadora portátil solo puede contener muchos servicios de lenguaje mecanografiado, y algunos de ellos ya lo son:

    • uno de vscode

    • uno de tslint

y no quiero agregar otro encima de eso

Desearía tener una mejor manera de conectar mis transformadores de código, pero tenemos lo que tenemos


y así es como hacemos las macros: #4892

  • mi computadora portátil solo puede contener muchos servicios de lenguaje mecanografiado, y algunos de ellos ya lo son:

    • uno por vscode
    • uno por tslint

@ zpdDG4gta8XKpMCd Creo que todo debería estar usando el mismo servicio de idioma. Entonces tendrá un servicio de un solo idioma y luego el complemento tslint junto con su complemento lo representarán.

Por cierto, lo que está tratando de hacer aquí definitivamente debería ser posible con un complemento de servicio de lenguaje sencillo porque eso es lo que se hace aquí .

De todos modos, tratemos de mantener la conversación aquí sobre el tema y solo sobre los transformadores personalizados como parte de la compilación con tsc en lugar de cambios en el código del editor/cosas del servicio de idioma. La mayoría de las personas buscan una solución para hacer una transformación en todo un proyecto y hacerlo dentro del editor no es una solución viable (especialmente porque hacer una transformación en ese punto anula el propósito de usarlos). Idealmente, lo que debería implementarse aquí no debería tener nada que ver con el editor/tsserver o el servicio de idiomas.

gracias por tu valioso aporte lo tendre en cuenta

No estoy de acuerdo con usted en mantener la conversación solo sobre transformadores personalizados como parte de la compilación con tsc , ya que

  • la solicitud original tal como está escrita no es específica en qué forma se entregarán las transformaciones, solo establece que no deberían requerir tener que
    > duplique toda la línea de comando tsc solo para agregar un solo transformador
  • durante 2 años, esta discusión ha atraído bastante la atención de muchas personas a las que no parece importarles mucho cómo se implementan los transformadores, siempre que haya una solución, funcione y sea fácil de usar
  • Además, el equipo de tslint hizo un buen trabajo al crear la infraestructura para complementos, no usarla es una pérdida de esfuerzo, siempre que sea de facto la única plataforma reconocida oficialmente fuera de TypeScript que se ocupa de TypeScript.
  • Además, todos estamos de acuerdo en que incluso si los transformadores alguna vez encuentran su camino hacia el idioma, no sucederá pronto, pero la gente aquí (incluyéndome a mí) los necesitaba como ayer.
  • por último, dado que no hay muchas alternativas mejores, ¿por qué no consideramos al menos lo que tenemos?

mi sugerencia está claramente etiquetada como una solución alternativa (mientras que el equipo de diseño se toma su tiempo para pensar más en una solución adecuada), entonces, ¿por qué no?

si insiste en que deberíamos hacerlo en otro lugar, por favor hable

pero para abordar su propia preocupación de hacer un

transformar a lo largo de todo un proyecto

tslint hace exactamente eso con su argumento --fix para cli

@zpdDG4gta8XKpMCd --fix actualizará el código TypeScript en su lugar. Este problema se trata de hacer transformaciones durante la emisión (por lo que los cambios solo terminan en los archivos JavaScript finales). Consulte el PR del problema al que se hace referencia (n.º 13940):

Desde que llegó #13764, es fácil escribir transformadores personalizados. Sin embargo, si entiendo la API correctamente, es necesario duplicar toda la línea de comando tsc solo para agregar un solo transformador. Esto conduce a incompatibilidades ya que estas aplicaciones, según el mecanografiado, no admiten las mismas funciones que la herramienta de línea de comandos tsc.

En otras palabras, ese problema trajo CustomTransformers (haga clic en ese enlace y vea dónde se usa en la API), pero para usarlos, tsc debe duplicarse de alguna manera o envolverse, que es lo que ttypescript lo hace. Luego, el segundo párrafo habla sobre cómo esto sería bueno porque se integraría muy bien en las herramientas de compilación existentes (ya que tsc manejaría los transformadores personalizados para usar en lugar de que las diferentes herramientas de compilación lo hicieran de diferentes maneras).

Creo que sería más productivo abrir un nuevo problema con sus inquietudes sobre las correcciones de código o si desea una forma más fácil de generar código TypeScript dentro del código TypeScript. No estoy seguro de cuáles son exactamente esas preocupaciones, ya que creo que muchas de ellas ya son posibles hoy en día, pero lo que ha estado discutiendo es cómo hacer correcciones/acciones de código, lo que me parece un tema no relacionado.

Creo que las preguntas principales que se deben responder en este hilo son las que discutió Daniel: "tal vez haya algo más amplio que solo los transformadores previos y posteriores", y cómo sería la solución para hacer que esto sea parte de la compilación.

eres vago

soy una persona que entiende y aprecia las cosas simples

mi problema es que estoy lidiando con un proyecto de más de 3500 archivos, de los cuales el 15% no necesita ser escrito y mantenido a mano y hay alrededor del 5% de cosas similares por venir

Al mismo tiempo, sé que hay una API que puede hacerlo por mí, pero está tan mal hecha que nunca puedo justificar mi tiempo lidiando con ella para que esté completamente lista.

así que cuando vine aquí pensé que este era el lugar adecuado para hablar de ello, y resulta que podría haber una solución rápida y sencilla.

mala suerte algunas personas que vinieron aquí son para discutir algunos asuntos mucho más finos

bien, excelente!

y no, no voy a abrir un nuevo problema solo para mostrarle a la gente una vez más cómo tslint puede resolver uno de los principales problemas, hice mi trabajo, he terminado

Tener transformaciones configurables listas para usar sería bueno. Estoy tratando de abordar un problema de cadena en código l10n y i18n . Puedo aprovechar herramientas como tslint con una regla personalizada para la extracción, pero mis opciones para transformar el código son limitadas, a menos que use algo como ttypescript , pero eso es problemático porque la aplicación que estoy trabajando es una aplicación angular no expulsada. Simplemente me obliga a agregar capa tras capa de herramientas de construcción. Con el ritmo de desarrollo, toda la pila se vuelve realmente precaria.

Actualmente estamos desarrollando un marco y actualmente estamos usando ttypescript para acceder a la información de nivel de tipo en tiempo de ejecución, sería bueno tener la opción plugins en el compilador oficial eventualmente 😄

Estoy de vacaciones en este momento, pero miraré la próxima semana cuando regrese.

El domingo 21 de julio de 2019 a las 17:54 Giorgio Boa [email protected]
escribió:

@longlho https://github.com/longlho Creaste un montón de geniales ast
transformadores, necesito su ayuda por favor 👍
Realmente me gustaría modificar los metadatos del decorador antes de la compilación angular.
Mi objetivo es modificar este nodo.
Componente ({selector: 'estándar' ... }) en Componente ({selector: 'personalizado'
... })
Hice un repositorio de github para probarlo
https://github.com/gioboa/ng-ts-transformer . creo que es posible pero
sin documentación necesito ayuda. 🙏 Gracias.


Estás recibiendo esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/microsoft/TypeScript/issues/14419?email_source=notifications&email_token=AABQM335QEEDNVT4NUICJQDQASBDXA5CNFSM4DCFER5KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2OGIWQ#issuecomment-57635,6
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AABQM33S5IYXB5HOZTRVVX3QASBDXANCNFSM4DCFER5A
.

He contribuido a crear una biblioteca para crear simulacros reales de interfaces sin proxy. Recomiendo usar ttypescript por ahora, pero sería bueno tener una forma integrada con mecanografiado

Realmente me encantaría ver que esta función suceda. Estoy bastante seguro de que esto es lo único que se interpone entre Typescript y algunas de las mayores innovaciones a las que puede conducir.

El texto mecanografiado es una gran contribución al desarrollo de la interfaz, pero también frena la innovación...
No rompa la semántica. Ningún complemento ATM no puede romper la semántica; y no se permiten complementos en absoluto :man_shrugging: ¿Por qué?
Hay plugins realmente buenos, pero. Cada complemento debe respetar la tokenización de palabras (clave) y la instalación AST)..., una forma realmente difícil de hacer algo por dentro.
No es tan difícil. No es fácil, pero babel project demuestra que es posible.
De hecho, es casi trivial para babel introducir nuevas frases semánticas o incluso sintácticas.

No espero que TypeScript permita la semántica. (¡Tampoco espero cambios de sintaxis, por supuesto!)
Lo que deseo del compilador es el cambio en algunos casos, como (puede ser solo tipo) preeval.
Por ejemplo, si tengo una función tomada, como route o message o algo así, el compilador puede preevaluar y (oh, por favor, en la fase uno) verificar la corrección.

Si estás leyendo mi párrafo anterior raro. ¿Qué es tsx y todas las bondades de React?

Sin React, sin flujo, sin mecanografiado en absoluto, casi sin un vistazo.

Por favor. Estoy bien entendiendo la mirada cuidadosa de pie en todo esto; pero como aprendemos de IE5.5+; bloquear no es un camino a seguir.

Si algo necesita mejoras, sigue siendo el motor de diseño. D.Knuth fue el genio que diseñó todas las piezas faltantes hace 50 años. ¿Por qué no tenemos esto hoy? :-)
Por favor, dígale a la gente que detenga el CSS en la maldad de JS.

Por favor. Open TS para inteligencia semántica ; como función con entrada de cadena estática, proporcionando una sugerencia de tipo para el resto; analizar la cadena de entrada const real...
Un pequeño ejemplo:

  • Forma de retorno de llamada de GraphQL
  • Forma de entrada internacional
  • …mucho más_
    Por favor. No se necesitan cambios de semántica. Todo funcionará como se desee. Se puede verificar algo más en el momento de la compilación. ¡Eso es todo amigos! :Conejo:

protuberancia

Estoy experimentando con la escritura de transformaciones TS para la optimización core-js import - polyfilling automático para entornos de destino, como @babel/preset-env y @babel/runtime , pero sin babel . Podría ayudar seriamente a una gran parte de los desarrolladores de TS. Pero sin admitir transformaciones personalizadas desde el cuadro sin herramientas adicionales como ttypescript , la posibilidad de usar esas transformaciones estará seriamente limitada, por lo que no estoy seguro de que tenga sentido.

He estado experimentando con esa idea: https://github.com/webschik/typescript-polyfills-generator.
Creo que la API de Transformers abrirá la posibilidad de eliminar babel de la cadena de desarrollo. Creo que muchos desarrolladores no quieren usar ambos, pero aún necesitan complementos como @babel/preset-env .

Actualmente hemos lanzado nuestro propio script compilador personalizado (usando la API del compilador TypeScript) debido a esta limitación. Examinamos brevemente ttypescript , pero el deseo de pasar del compilador de TypeScript estándar a una extensión del compilador de TypeScript simplemente no existe.

Sería fantástico si los transformadores personalizados fueran compatibles con tsconfig.json. Es engorroso escribir un script que simplemente analiza tsconfig, declara los transformadores y luego ejecuta el compilador; o, peor aún, intentar e intentar volver a implementar las características fundamentales del compilador, como ver archivos, en un script personalizado.

Otras personas se han hecho eco de este sentimiento, pero permitir la facilidad de integrar transformadores personalizados en el compilador quitaría una carga significativa del equipo de desarrollo de TypeScript y permitiría la innovación y un impulso adicional con este lenguaje de la comunidad.

Un ejemplo de un ecosistema de complementos muy exitoso es la comunidad de complementos de Serverless Framework. El equipo de desarrollo no puede mantenerse al día con la demanda de desarrollo de funciones, y los complementos son una excelente manera de permitir la integración de funciones nuevas (posiblemente experimentales) sin la necesidad de abrir relaciones públicas o diluir el producto principal con funciones que pueden o pueden no proporciona valor a la base de usuarios más amplia.

Estoy construyendo una biblioteca y tengo decoradores que funcionan muy bien para mí y de los que dependo. Hace algún tiempo me di cuenta de que los decoradores hacen que mi biblioteca no sea sacudida por árboles. Después de investigarlo, llegué a la conclusión de que los transformadores podrían ayudarme a convertir esos decoradores en un código que se puede sacudir en el árbol al compilar. Es lamentable que no pueda definirlos en mi tubería. Espero que aborde este problema pronto, solo quería dejar mis 2 centavos en un caso de uso en el que sería muy útil.

Con el interés de hacer que TypeScript admita transformadores personalizados sin programas de envoltura e instrucciones complicadas, he escrito una herramienta llamada ts-patch ( npm github )

Simplemente instale ts-patch (global o localmente) y ejecute ts-patch install para parchear el mecanografiado. También puede especificar el directorio de instalación de TypeScript y/o habilitar la persistencia, que mantiene el parche si TS se actualiza o reinstala. (detalles: ts-patch /? )

La lógica del parche se basa principalmente en ttypescript. (¡Muchas gracias al gran trabajo de cevek!) Está escrito de una manera que se puede agregar fácilmente al proceso de instalación del paquete npm. También es fácil de desparchear.

Para ser claros, esto parchea directamente los archivos relevantes en el mecanografiado y no es un contenedor. Simplemente ejecute el parche después de la instalación de la dependencia y TypeScript estará listo para el transformador.

¡Espero que esto ayude a algunas personas!

Con el interés de hacer que TypeScript admita transformadores personalizados sin programas de envoltura e instrucciones complicadas, he escrito una herramienta llamada ts-patch ( npm github )

Simplemente instale ts-patch (global o localmente) y ejecute ts-patch install para parchear el mecanografiado. También puede especificar el directorio de instalación de TypeScript y/o habilitar la persistencia, que mantiene el parche si TS se actualiza o reinstala. (detalles: ts-patch /? )

La lógica del parche se basa principalmente en ttypescript. (¡Muchas gracias al gran trabajo de cevek!) Está escrito de una manera que se puede agregar fácilmente al proceso de instalación del paquete npm. También es fácil de desparchear.

Para ser claros, esto parchea directamente los archivos relevantes en el mecanografiado y no es un contenedor. Simplemente ejecute el parche después de la instalación de la dependencia y TypeScript estará listo para el transformador.

¡Espero que esto ayude a algunas personas!

¿Podría esto plantearse como un PR para agregar/discutir el soporte adecuado? :)

Oye. Por lo que vale, hay un paquete llamado caja de fusibles que hace que sea muy fácil agregar transformadores personalizados. Su versión 4.0 llegará pronto... así que está en un punto intermedio. Pero en general, me gusta mucho el paquete. Quizás te pueda ayudar a ti también.

https://github.com/fuse-box/fuse-box/blob/master/docs/plugins/pluginCustomTransform.md

¿Podría esto plantearse como un PR para agregar/discutir el soporte adecuado? :)

El equipo de TS ha expresado que no quieren proporcionar esto como una función nativa. ¡Sus razones para la decisión tienen sentido!

La buena noticia es que debido a que TS es de código abierto y ya está compilado de forma modular, ts-patch se comporta de una manera muy parecida a como lo haría si estuviera integrado. Por lo tanto, no es como un parche de bytecode de ingeniería inversa con errores.

Si por soporte, le preocupa que se mantenga, planeo mantenerlo actualizado y funcionando para todas las versiones futuras de TS. Mucha de mi infraestructura comercial ya depende de ello.

Como nota al margen, pronto lanzaré una nueva versión que permite empaquetar múltiples complementos con diferentes puntos de entrada en un solo paquete, así como algunas otras optimizaciones para mejorarlo y hacerlo más fácil de usar.

Después de escribir un complemento, puedo apreciar por qué el equipo de ts duda: el transformador de corriente es un paso posterior a la compilación. Te encuentras con problemas desagradables si haces algo complicado y comienzas a agregar contenido nuevo que no estaba enlazado originalmente. Tal como está, ts-node --compiler ttypescript foo.ts funciona perfectamente bien. Prefiero que el equipo de ts se ocupe de los complementos de transformadores en diferentes pasos de compilación... o permita un paso de reenlace.

El transformador de corriente es un paso posterior a la compilación. Te encuentras con problemas desagradables si haces algo complicado y comienzas a agregar contenido nuevo que no estaba enlazado originalmente.

Los transformadores pueden ejecutarse antes o después de la compilación TSC. Parece que a lo que te refieres es que el verificador no se actualiza después de modificar los nodos. En realidad, esto se puede eludir, la funcionalidad simplemente no se creó para ello. Cuando invoca ts.transform(), no crea una instancia de programa completa para que pueda trabajar, por lo que si desea trabajar con el comprobador, debe crear uno. Con CompilerHost, puede volver a cargarlo con los archivos modificados después de modificar el AST.

Todavía no me he metido demasiado en esto, pero parece que también es posible usar la funcionalidad 'observar' para evitar tener que reconstruir toda la instancia del programa cada vez. En pocas palabras, resulta que en realidad no es _demasiado_ difícil tener un sistema de complementos más completo, pero transform simplemente carece del soporte en el contexto proporcionado.

@nonara He usado transformaciones con ttypescript y ts-loader`, ambos tienen puntos de entrada completos al programa. Mi problema es que si agrega una nueva declaración de importación, falta "algo" y esas nuevas declaraciones se eliminan de la emisión de salida final. @weswigham dice que es porque la transformación es un paso posterior al enlace . Aparentemente, la solución es crear un programa completamente nuevo para el archivo, pero eso parece un dolor de cabeza cuando se trata de cosas como ts-loader (especialmente cuando está en modo de solo transformación y oculta por completo el archivo webpack/bundler). resolver Al final , dejé la importación y simplemente inserté el código que necesitaba .

@MeirionHughes Ah, está bien. En ese caso, sí, tiene una instancia de Programa. ttypescript funciona conectando createProgram para parchear el método de emisión resultante program para incluir los transformadores.

  • ts.emitFiles llama a ts.transformNodes durante el proceso.
  • ts.transformNodes se puede llamar con o sin una instancia de programa. Llamar directamente a ts.transform() lo hace sin uno.

Si lo entiendo correctamente, parece que su problema también está relacionado con el hecho de que los tipos y símbolos ya se han recorrido, y no se actualizan después de la transformación AST.

Hola a todos, he estado escribiendo un manual de transformadores para colocar toda la información sobre los transformadores y para que sea más fácil comenzar.

https://github.com/madou/ts-transformer-handbook/blob/master/translations/en/transformer-handbook.md

Me encantaría algunos ojos en él si puedes dedicar un segundo 👍

@madou También escribí un montón de publicaciones sobre transformadores TS https://levelup.gitconnected.com/writing-typescript-custom-ast-transformer-part-1-7585d6916819

¿Cuál es el estado de esto?

Me encanta mucho el mecanografiado, pero se siente especialmente torpe cuando comienzas a interoperar entre tipos estáticos y JS en tiempo de ejecución. Existen numerosos complementos escritos por la comunidad para mejorar esto, por ejemplo, https://github.com/dsherret/ts-nameof , https://github.com/kimamula/ts-transformer-keys , pero sin compatibilidad con complementos de primera clase. se siente como una decisión técnica arriesgada para incluirlos en un proyecto. Habilitar los complementos de forma nativa permitiría a la comunidad jugar con posibles características futuras de mecanografiado, antes de que deban incluirse en la biblioteca principal.

Creo que el equipo de TypeScript debería reconsiderar su argumentación. El ecosistema de complementos es una forma comprobada de hacer avanzar el lenguaje, permitiendo (y fomentando) los experimentos (ver Haskell con sus pragmas).

Algunos de esos experimentos serán salvajes y locos, y algunos eventualmente se estabilizarán y se volverán comunes. Siempre es bueno proporcionar la capacidad de implementar funciones de lenguaje en el espacio del usuario.

En general, la posición del equipo de TypeScript parece innecesariamente rígida.

También hay transformaciones que no cambian el idioma pero brindan información adicional para facilitar la depuración.

Por ejemplo , babel-plugin-transform-react-jsx-source es parte del ajuste predeterminado de transpilación de reacción ( @babel/preset-react ).
se transforma

<sometag />

Dentro

<sometag __source={ { fileName: 'this/file.js', lineNumber: 10 } } />

Esta información permite que react proporcione un mejor seguimiento de la pila de errores durante el desarrollo.

Para mecanografiado no hay una forma estándar de lograr lo mismo, aunque hay una transformación de código abierto: https://github.com/dropbox/ts-transform-react-jsx-source

Entiendo que @mhegazy mencionó dos veces que el equipo de TS no tiene planes de incluir "complementos" como parte de tsconfig. ¿Cuál es el razonamiento detrás de esto?

¿Estaría abierto a un PR? La forma en que ttypescript maneja los transformadores a través de tsconfig es bastante agradable.

Casos de uso:

1) generar tipos de interfaz para esquemas para que puedan verificarse en tiempo de ejecución.
2) importar json con cadenas como literales para que TypeScript no vomite cuando se asigna a un tipo con uniones discriminadas.
3) importar css/yaml y otro objeto como sintaxis
4) hacer consultas de graphql que crean dinámicamente los tipos correctos
5) compilar jsx en cadenas html para que puedan inyectarse en HTML interno
5) reescribir importaciones absolutas a importaciones relativas basadas en rutas tsconfig.

La lista sigue y sigue. La API del complemento es agradable. Gracias por aterrizarlo. Tener "complementos" como parte de "tsconfig" hace que tsc sea realmente poderoso. ¿Hay algo grande que nos estamos perdiendo?

también puede hacer muchas optimizaciones de rendimiento. He estado escribiendo https://github.com/atlassian-labs/compiled-css-in-js con transformadores mecanografiados 🤙 sería genial si los consumidores no tuvieran que pasar por el aro para usarlo.

Estimado equipo de Typescript, dejen de dar largas a esto <_<

¿Cuál es el estado de esto?

¿Estado?

Amigos que novedades?

El equipo de mecanografiado se ha decidido en contra de esta idea: si necesita flexibilidad o mejores herramientas de desarrollo, el uso de mecanografiado no es una opción sin trucos, vaya con babel y use mecanografiado solo para la verificación de tipos.

El equipo de mecanografiado se ha decidido en contra de esta idea: si necesita flexibilidad o mejores herramientas de desarrollo, el uso de mecanografiado no es una opción sin trucos, vaya con babel y use mecanografiado solo para la verificación de tipos.

Pero, ¿y si quiero algunos trucos para la verificación de tipos? Escribo un pequeño transformador que hace algo de magia:

type Human = {
    name: string,
    age: number
}

const isValid = check<Human>({ name: 'Carl', age: 16 }) // => true
const isValid = check<Human>({ name: 'Carl' }) // => false

¡Función check transformada en una función de protección de tipo específica! ¿Cómo puedo hacerlo con Babel? Actualmente, debería usar ttypescript...

El equipo de mecanografiado se ha decidido en contra de esta idea: si necesita flexibilidad o mejores herramientas de desarrollo, el uso de mecanografiado no es una opción sin trucos, vaya con babel y use mecanografiado solo para la verificación de tipos.

En realidad, se habla de que esto será compatible en el futuro. Dicho esto, realmente ya es compatible. La API del compilador de TypeScript admite transformadores, y es _realmente_ simple escribir un compilador personalizado que use transformadores en solo unas pocas líneas de código.

Pero para hacerlo más fácil, puede usar ttypescript o ts-patch .

Estas bibliotecas no son realmente "trucos" en el sentido de que no aumentan el compilador para agregar capacidad de transformación. En su lugar, simplemente exponen la funcionalidad existente de la API del compilador a tsc , haciéndola utilizable a través de tsconfig.

@ilya-buligin si entiendo su caso de uso correctamente, puede declarar una constante ambiental

declare const check: <T>(value: unknown) => value is T;

const isValid = check<Human>({ name: 'Carl', age: 16 }) // => true

TypeScript compilará el código basándose en la definición de tipo check y luego lo reemplazará con un código generado usando Babel.

@just-boris, ¿cómo puedo obtener acceso al tipo genérico <T> en Babel?

Este hilo se está volviendo bastante repetitivo y fuera de tema. @RyanCavanaugh Tal vez este hilo debería estar bloqueado, hasta que tenga alguna actualización sobre el tema.

¿Fue útil esta página
0 / 5 - 0 calificaciones