Typescript: Suporte de plug-in para transformadores personalizados

Criado em 2 mar. 2017  ·  99Comentários  ·  Fonte: microsoft/TypeScript

Desde que o #13764 chegou, é fácil escrever transformadores personalizados. No entanto, se eu entendi a API corretamente, é necessário duplicar toda a linha de comando tsc apenas para adicionar um único transformador. Isso leva a incompatibilidades, pois esses aplicativos, dependendo do texto datilografado, não suportam os mesmos recursos que a ferramenta de linha de comando tsc.

Portanto, seria favorecido ter um sistema de plugins que permitisse carregar Transformadores Personalizados de módulos de nós de terceiros, como é o caso dos proxies de serviço de linguagem #12231. Esses transformadores se integram facilmente às ferramentas de construção/fluxos de trabalho de construção existentes.

Se alguém experiente tiver sugestões sobre como implementar as mudanças, estou disposto a criar um PR, pois simplificaria tremendamente meu projeto.

Docs

Comentários muito úteis

Eu não quero ter uma API de plugin exposta. Em vez disso, eu preferiria registrar minhas transformações personalizadas apenas especificando-as no tsconfig.json em vez de ter que usar a API do TS-Compiler. Porque usar a API do TS-Compiler implica que não posso mais usar a ferramenta de linha de comando tsc, o que pode implicar que ela não se integra mais bem às ferramentas e fluxos de trabalho de compilação existentes.

Todos 99 comentários

Não planejamos expor o sistema de plugins do compilador a curto prazo. As transformações são expostas como parte da API pública, conforme você observou, e estamos escrevendo a documentação e as amostras para elas.

Eu não quero ter uma API de plugin exposta. Em vez disso, eu preferiria registrar minhas transformações personalizadas apenas especificando-as no tsconfig.json em vez de ter que usar a API do TS-Compiler. Porque usar a API do TS-Compiler implica que não posso mais usar a ferramenta de linha de comando tsc, o que pode implicar que ela não se integra mais bem às ferramentas e fluxos de trabalho de compilação existentes.

alguma atualização sobre documentação e amostras? @mhegazy

@MichaReiser você pode escrever um compilador simples baseado na API (exemplo aqui ). Na verdade, usamos muito o TS no Yahoo Finance e a API pública do transformador tem sido incrível.

Esses são alguns dos transformadores que escrevemos depois que se tornou público:
https://github.com/longlho/ts-transform-system-import
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 se precisar de ajuda para documentar/coletar amostras

@longlho
Obrigado por sua amostra.

É o que estou fazendo atualmente. No entanto, torna impossível usar outras ferramentas de compilação criadas para typescript, por exemplo, carregadores de pacotes da web, carregadores de jest. Além disso, como posso usar um de seus plugins junto com um dos meus quando cada um de nós usa um frontend diferente?

Portanto, acredito que a abordagem atual é um bom começo, mas não suficiente para um ecossistema de plugins. Porque usar um plugin é muito trabalhoso para o usuário e requer mais do que apenas escrever o código de transformação para o autor.

Acredito que um sistema de plugins como o do Babel é essencial para o typescript se o objetivo é incentivar a comunidade a criar e usar transformadores personalizados.

@MichaReiser sim. Não estou dizendo que é suficiente para o ecossistema, apenas bom o suficiente para o 1º passo em direção a ele.

Eu gostaria de adicionar suporte para transformações em gulp-typescript, mas quero evitar que todos os plugins TypeScript (para gulp, webpack etc) proponham uma API diferente. E o TypeScript pode adicionar até uma maneira diferente de configurar isso mais tarde. Então, você atualmente tem planos de adicionar isso em um futuro próximo ou distante?

Olá a todos, tento escrever um pré-processador, mas nada sai :[

Na verdade, tenho duas perguntas:

  • Como criar um fragmento AST a partir de uma string?
  • Como adicionar importação?
// 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;
}());

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

⬆️ ⬆️ ⬆️
@longlho , @mhegazy Você pode dar alguma dica?

@RubaXa Como você adicionou a declaração de importação em uma transformação, ela não é vinculada ou verificada por tipo. Como não foi vinculado ou verificado por tipo, não podemos resolver __LIB__ em sua expressão para __LIB__ na declaração.

Uma opção é usar uma importação de namespace em vez de uma importação padrão, para que sua emissão seja algo como:

import * as __LIB__ from "@external/lib"

Como não há aliasing que pode ocorrer.

O outro guarda um identificador gerado para a declaração de importação, conforme o zip anexado

@RubaXa se seu objetivo é passar todo o objeto do módulo, você provavelmente deseja usar a sintaxe import * as __LIB__ from "@external/lib" (que não requer alias) e não import __LIB__ from "@external/lib" , pois o último importa o default export em vez de todo o objeto do módulo.

sim, estamos fazendo import * as foo em nosso transformador de módulos CSS também para evitar alias. Embora seja bom aproveitar isso para embutir certas exportações nomeadas

@rbuckton O, muito obrigado!
Ainda interessado em como criar um fragmento AST arbitrário de uma string?

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;
}

Isso é o que eu esperava que o suporte e o fluxo de trabalho do transformador se comportassem como no TypeScript.

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

Eu também estou muito interessado neste recurso.

como @MichaReiser mencionou
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.

adoro ver entradas de especialistas/compilador typescript DEV .

Parece que alguém embrulhou o texto datilografado para expor essa funcionalidade. https://github.com/cevek/ttypescript

Também parece que o ts-loader tem: https://www.npmjs.com/package/ts-loader#getcustomtransformers -----before-transformerfactory--after-transformerfactory----

Acho que isso é algo que pode chegar na versão 2.8 datilografada ou pelo menos no roteiro em algum momento, @ahejlsberg @mhegazy @DanielRosenwasser o que você acha? Dessa forma, os transformadores personalizados podem ser mais populares e, portanto, mais poderosos. Ter a opção de plugar no transfromer da perspectiva do tsconfig.json simplificaria muito a vida.

Não temos planos de expor plugins no curto prazo, conforme observado anteriormente.

@mhegazy É uma decisão considerada ou está fora do escopo apenas por causa do baixo interesse da comunidade?

Eu não disse isso. gostaríamos de manter um pequeno custo público de API/manutenção, bem como flexibilidade na mudança de como a construção é conduzida no futuro, e ambos são afetados por um modelo de plug-in.

Por favor, pare a fragmentação da API do plugin do transformador. Estabilize a API do plugin em cima da API do transformador e exponha-as em tsconfig.json.

ts-loader , parcel-plugin-typescript , rollup-plugin-typescript2 , ts-transformer-keys , ttypescript e outros.

Cada um deles fornece um método de registro de plug-in personalizado e um formato de ponto de entrada de plug-in personalizado. É uma maneira de ts plugin inferno.

Agora cevec/ttypescript suporta todos os formatos comuns de plug-in de transformador. É um wrapper drop-in em cima de todos os módulos typescript e comandos tsc, tsserver (apenas um pequeno patch de tempo de execução ts.createProgram). Webpack ts-loader e rollup-plugin-typescript2 podem ser facilmente configurados com ttypescript.

TTypescript sugere o formato de plug-in de transformador universal, mas os transformadores existentes também são suportados.

{
    "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/**/*"]
}

Algumas notícias sobre este? Parece-me que os autores do TypeScript de alguma forma não querem permitir transformadores personalizados no TypeScript vanilla - isso é uma pena, seria um recurso incrível.

eles não querem outra api/superfície para manter por medo de levar à dificuldade de quebrar coisas nos internos. Ironicamente, todas essas soluções de plug-in de terceiros são, porque não há um padrão da ts-team, todas um pouco diferentes e quebrarão eventualmente.

eles não querem outra api/superfície para manter por medo de levar à dificuldade de quebrar coisas nos internos.

Após 3 anos trabalhando com datilografia e observando sua evolução, cheguei a uma conclusão simples. A Microsoft tem Typescript de código aberto no sentido de _code_, mas não no sentido de _process_. Na maioria dos casos, os projetos de código aberto são mais ou menos orientados pela comunidade tanto nas decisões quanto na codificação , e essa deve ser a maneira natural de evoluir. Você se lembra do fork IO.js do node.js? A comunidade percebeu que os interesses da empresa não estavam tão alinhados com o modelo comum de governança de código aberto e simplesmente se bifurcaram. Espero que isso não aconteça para o TypeScript, mas a Microsoft deve levar em consideração essa possibilidade.
Para ser claro, não estou culpando os desenvolvedores, de qualquer forma, eles fazem um ótimo trabalho, realmente.
Apenas meu 2c, desculpe o OT.

A Microsoft tem Typescript de código aberto no sentido do código, mas não no sentido do processo.

Eu discordo totalmente disso. Nunca trabalhei para a Microsoft, mas tive influência direta em vários recursos do TypeScript nos últimos 4 anos. Eu estava representando uma biblioteca de código aberto construída em TypeScript, e combinamos de ter algumas conversas diretas, mas todo o "debate" de qualquer recurso foi aberto, em público, aqui. A equipe principal publica suas notas de reunião de design. A única "insider" que recebi, representando uma biblioteca de código aberto, foi uma oportunidade de argumentar pessoalmente sobre alguns recursos e conhecer a equipe principal. Isso me fez perceber que a equipe atua como uma equipe. Um recurso sobre o qual falamos, Anders basicamente disse que o problema era muito difícil e que levaria muito tempo para resolvê-lo e resolver os problemas "reais" enfrentados pelas pessoas. Isso foi há dois anos e no TypeScript 3.0 finalmente conseguimos. Mas a comunidade tem uma voz no processo de design, mas como qualquer comunidade, nós fabricamos várias vozes, e nenhuma equipe em qualquer lugar poderia agradar a todos e, se o fizessem, o TypeScript seria uma ferramenta _realmente_ ruim.

Você também deseja rotular a equipe principal como "Microsoft". A equipe principal foi a equipe menos Microsoft que eu já encontrei. Eles travaram batalhas para obter o controle total de sua cadência de lançamento, depois de terem sido fundados no controle total do conteúdo de seu lançamento. Eles também lutaram por abertura e transparência. Eles lutaram para mudar para o GitHub do CodePlex. É certo que eles não são mais tão únicos na Microsoft, já que várias outras equipes adotaram seu modelo, mas foram, até onde eu sei, os que começaram tudo, com a equipe do VSCode seguindo logo depois.

Então, só porque a equipe principal escolhe suas batalhas, seguir seus Princípios de Design não significa que a comunidade não tenha voz, mas como uma voz sofremos de transtorno psicótico de personalidade múltipla. Somos um cliente difícil de atender.

Meu entendimento é que isso é o mesmo que #16607, ou isso atingiria um objetivo diferente? Como um autor de plugin muito recente, eu também gostaria de ver isso exposto - inclusive ao trabalhar com TypeScript usando o plugin Babel.

@mrmckeb este problema é para padronizar e expor a transformação AST de script datilografado, que já existe, enquanto o problema vinculado parece estar discutindo a transformação de arquivo inteiro em um escopo muito amplo (indefinido).

Eu quero adicionar meus 2 centavos aqui. Alguns de vocês já devem ter ouvido falar do brilhante projeto babel-plugin-macros . Basicamente, em vez de ter milhares de plugins Babel diferentes, pode haver o único que é alimentado por um código de usuário para fazer uma transformação. Um sistema incrivelmente transparente sem a necessidade de mexer na configuração o tempo todo. Isso é especialmente ótimo para projetos como o CRA , que suporta macros, mas proíbe configurações adicionais.

Hoje eu abri a discussão sobre como possivelmente levar isso para o mundo TypeScript. Se você tiver algum insight, por favor, venha e compartilhe.

Em última análise, espero que, se de alguma forma tivermos sucesso, não haverá necessidade disso, pois apenas uma transformação será necessária.

@FredyC esse é um projeto legal, mas precisaríamos que esse problema fosse resolvido para injetar facilmente algo assim no compilador ao usar apenas tsc . Por exemplo, com babel-plugin-macros ele ainda precisa ser especificado em .babelrc e seria bom especificar algo assim no typescript em tsconfig.json .

Na verdade, você está sugerindo que seria bom ter um comportamento semelhante ao babel-plugin-macro embutido no TypeScript e nenhuma configuração seria necessária? Isso pode ser bom, mas pessoalmente eu preferiria uma solução configurável que permite especificar transformadores personalizados em tsconfig.json e, em seguida, uma versão do babel-plugin-macros que suporta nós ast typescript poderia ser especificada.

@dsherret Sim, não espero que faça parte do próprio TypeScript. No entanto, posso imaginar que, uma vez que a transformação esteja pronta, pode ser fácil preparar um minúsculo wrapper do tipo tsc que injetaria apenas essa transformação para macros e o resto poderia ser feito a partir de um código de usuário.

Edit: Na verdade, o minúsculo wrapper já está lá, com o https://github.com/cevek/ttypescript mencionado acima, seria fácil instruir a usá-lo junto com o plug-in de macros universal e é um ganha-ganha.

Eu só preciso encontrar pessoas que sejam bem versadas em transformações do Typescript para descobrir algum protótipo básico. Eu posso discutir e falar, mas implementá-lo está acima do meu conjunto de habilidades atual.

eles não querem outra api/superfície para manter por medo de levar à dificuldade de quebrar coisas nos internos.

Após 3 anos trabalhando com datilografia e observando sua evolução, cheguei a uma conclusão simples. A Microsoft tem Typescript de código aberto no sentido de _code_, mas não no sentido de _process_. Na maioria dos casos, os projetos de código aberto são mais ou menos orientados pela comunidade tanto nas _decisões_ quanto na _codificação_, e essa deve ser a maneira natural de evoluir. Você se lembra do fork IO.js do node.js? A comunidade percebeu que os interesses da empresa não estavam tão alinhados com o modelo comum de governança de código aberto e simplesmente se bifurcaram. Espero que isso não aconteça para o TypeScript, mas a Microsoft deve levar em consideração essa possibilidade.
Para ser claro, não estou culpando os desenvolvedores, de qualquer forma, eles fazem um ótimo trabalho, realmente.
Apenas meu 2c, desculpe o OT.

Eu concordo. É claro que, apesar do forte interesse da comunidade, os desenvolvedores estão simplesmente rejeitando a ideia de transformadores/macros personalizados sem realmente fornecer uma razão para a rejeição, exceto algo como "As pessoas usarão mal", o que também soa ofensivo para a comunidade como isso implica, é uma comunidade de desenvolvedores de baixa qualidade.

Eu aceitaria uma rejeição se uma justificativa razoável além de "Nós não vamos simplesmente fazer isso" pudesse ser fornecida, mas parece que, apesar de todos os pedidos da comunidade, ninguém ainda se esforçou para fornecer isso.

Acho que isso é uma crítica injusta @pietrovismara. Concordo que este é um recurso obrigatório, mas isso não é "Microsoft" bloqueando esse recurso. A equipe, pelo que entendi, está dizendo que isso não é fácil de suportar e é por isso que eles ainda não adicionaram esse recurso.

Mais uma vez, quero esse recurso tanto quanto qualquer outra pessoa - mas precisamos discutir essa questão usando fatos. Os fatos são que a equipe ainda não está pronta para apoiá-lo. Então, vamos continuar expressando interesse, mas também manter a conversa no caminho certo.

@mrmckeb Se for esse o caso, posso entender. Devo ter perdido tal declaração no grande fluxo de comentários contidos nessas edições. Não quis ofender ninguém, apenas tentar provocar uma resposta clara dos mantenedores para, como você disse, manter a conversa no caminho certo.

Tudo bem, é frustrante que o suporte para isso não exista - como eu disse, eu sinto isso, e nos pedem algum tipo de solução para módulos CSS o tempo todo no CRA agora que temos suporte a TypeScript. Espero que chegue logo, mas também entendo que abre uma enorme área de risco para a equipe.

... ainda esperando :(

sim, ainda esperando ..., mas esperando o que, algo foi feito?

Existe alguma solução melhor do que ttypescript agora?
Os desenvolvedores do TypeScript estão planejando oferecer suporte a plugins?

Você pode criar seu próprio compilador ;-)

Alguma novidade sobre o tema? Parece-me que a comunidade fez uso desse recurso extensivamente o suficiente para sentar, coletar feedback e, finalmente, adicionar suporte para transformadores ao arquivo de configuração. Existem ainda muitas implementações para usar como referência.

Já se passaram mais de 2 anos (uau!)*. As pessoas estão abertas a repensar os prós e contras de abrir plugins para transformadores?

Eu sinto que as preocupações iniciais que existiam todo esse tempo atrás, como a falta de documentação sobre a API e ter que suportar a malha de usercode <-> transformadores <-> API, não são mais tão relevantes. O suporte a plugins abertos fez maravilhas para pacotes como o babel: progressão através da colaboração. Posso atestar pessoalmente a Babel especificamente, tendo-a usado extensivamente.

A integração mais fácil "simplesmente funciona" de transformadores como typescript-is _seria_ bom. Este pacote em particular eu vejo como tendo silenciado a influência revolucionária no texto datilografado como um todo. Verdadeiros contratos fortes! 😃

Acho que uma conversa sobre os prós e contras ajudaria a dissipar qualquer desânimo ou diferenças sobre isso. Tenho a sensação de que esse problema zumbi continuará até que isso aconteça - para ser honesto.

* E, enquanto isso, alguém está criando o recurso para TS ( ttypescript ). Eu usei isso para o sucesso.

@DanielRosenwasser Vi que havia "Investigate APIs de plug-in TypeScript" no plano de iteração 3.5 (e esse trabalho já começou).
Esse ponto lida com o que é discutido nesta edição? A falta de um link para um problema me faz supor que é muito WIP para compartilhar algo sobre isso ainda?

Eu acho que o trabalho deve ser colocado na adição de suporte completo para o analisador Babel, que inclui a adição de recursos necessários para que o Babel suporte a análise estática do Typescript (por exemplo, várias transformações de arquivos ou dependência de vários arquivos durante a transformação). Em vez de ter que duplicar a sintaxe/transformar os plugins do Babel em equivalentes do Typescript.

caso você tenha algum problema com as instruções a seguir, me avise, ficarei feliz em ajudar

dada a pura negligência da equipe de design, aqui está uma solução alternativa

vamos aproveitar o tslint e seus recursos de correção de código

no exemplo a seguir vamos fazer uma transformação de tipo para código , em sua forma mais básica

vamos usar decoradores como marcadores de lugares no código que precisam ser reescritos

no nosso caso, um decorador é uma função falsa cujo único objetivo é

  • para marcar um lugar de transformação
  • e capturar o tipo que vai ser a fonte de informação para o gerador

para fins de demonstração, vamos despejar os nomes e tipos de propriedades de uma interface como strings simples, em uma classe subjacente

as etapas a seguir são apenas para usuários do Windows, se você não for um deles, que Deus o ajude:

  1. inicie seu VSCode
  2. instale a seguinte extensão: https://github.com/Microsoft/vscode-typescript-tslint-plugin
  3. feche seu VSCode
  4. vá para uma pasta de sua escolha
  5. correr git clone https://github.com/zpdDG4gta8XKpMCd/code-gen.git
  6. vá para a pasta code-gen : cd ./code-gen
  7. corre

    • 1-install.bat

    • 2-build.bat

    • 3-install-some-more.bat

    • 4-try.bat

  8. observe uma instância do VSCode aberta
  9. vá para test.ts ( Ctrl + P -> test.ts )
  10. anote a interface a seguir, ela será a fonte do gerador de código
interface Data {
    one: string;
    another: number;
}
  1. observe a seguinte função, que compreende um decorador fantasma que vamos usar como marcador
function gen<_T>() {
    return function (meh: any) {};
}
  1. anote o site de reescrita, onde queremos enfiar algum código de geração automática com base na interface e no decorador de marcadores
@gen<Data>()
export class Gen {
}
  1. observe uma linha ondulada em @gen<Data>()
    image

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

  3. observe o código gerado automaticamente:
    image


para a referência aqui está o código fonte do gerador que você pode encontrar em 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 , obrigado por compartilhar seu conceito - mas seja civilizado.

dada a pura negligência da equipe de design, aqui está uma solução alternativa

Esta não é a maneira apropriada de abordar o TypeScript por não implementar um _recurso_ que você (e muitos outros, inclusive eu) gostaria de ter. Este não é um defeito grave e não é reflexo de "negligência". Por favor, seja respeitoso.

oh, por favor, não leve para o lado pessoal, é assim que sempre começo minhas reclamações, tenho uma personalidade muito azeda (condição médica) e isso é o melhor que posso tirar de mim, sinto muito

vocês não vão parar de me surpreender

  • o que você vê é um pedaço de código que parece capaz de resolver um grande problema de hoje com conforto (sem truques, sem hacking)
  • essa solução alternativa é um alerta para a equipe de design e, como vimos isso acontecer antes, quando a comunidade estava prestes a dar uma guinada na direção errada, a equipe de design estava lá para abordá-la prontamente: #4212,
  • então, se eles se importam, eles podem fazer certo mais cedo até que seja tarde demais, ou se não o fizerem, somos livres para cavar nessa direção e não será um problema para eles no futuro
  • então o tom do meu feedback foi algo inapropriado, mas todo o tom apropriado seu não te trouxe nada desde 2 de março de 2017 (mais de 2 anos), e sim, você pode esperar mais 2 anos

@zpdDG4gta8XKpMCd O que você contribuiu para uma implementação real? O TypeScript é de código aberto; Não tenho dúvidas de que eles considerariam seriamente um pull request se você criasse um (mesmo que parcialmente).

Culpar sua grosseria por uma condição médica é inaceitável; são palavras que você digitou e voluntariamente escolheu clicar em "comentar". Nenhuma condição médica faz você fazer isso. Fale, talvez, não digite. Você também teve a chance de editar seu comentário para removê-lo, mas ainda não o fez.

Se você precisar de transformadores personalizados _agora_, poderá usar o Babel. Ele pode remover anotações de tipo de quase todos os TypeScript, enquanto permite transformações de sintaxe tão prontamente quanto você desejar. Como bônus, também é mais rápido.

Eu sugiro que você pare de comentar antes de ser expulso do repositório da Microsoft permanentemente. Eu sei que se fosse meu repo, você estaria em sua última gota.

ok, você me expulsou, então o que
posso voltar? posso criar uma nova conta?
você acha que eu me importo muito com essa conta?

enfim, sim, tentei pull requests, infelizmente não é viável pelos seguintes motivos:

  1. há uma certa categoria de problemas que você pode resolver, que são bastante triviais e de menor interesse, qualquer coisa séria como esta - e você não está

  2. como você não pode resolvê-lo sozinho, um problema como esse (mesmo com 224 polegares para cima) pode esperar anos se for considerado

  3. felizmente você pode fazer algo hoje usando qualquer meio que tiver e começar a fazer uma diferença que pode ser vista, daí a sugestão (não me culpe por não fazer nada)

@zpdDG4gta8XKpMCd Por mais que você saiba que sou fã das tomadas cínicas ao longo dos anos, tenho que concordar com os outros aqui - precisamos manter a conversa civilizada e respeitosa. É sempre bom lembrar que todos que estão acompanhando esse problema querem melhorar o projeto .


@Janpot Sim, é um WIP, embora quando @rbuckton voltar, ele possa dar mais detalhes sobre o status.

À medida que investigamos pontos de plugin (como eu mencionei no plano de iteração 3.5), acho que expor ganchos mais fáceis para transformadores personalizados é um cenário importante que queremos considerar. A razão pela qual não necessariamente faríamos isso diretamente é que poderíamos ter um trabalho mais amplo que inclui isso. Em outras palavras, talvez haja algo mais amplo do que apenas pré e pós-transformadores.

@DanielRosenwasser não há muito cínico nisso, eu só disse 2 palavras e depois disse que sinto muito por isso

de qualquer forma, acho que todos concordamos que há uma boa parte da frustração saudável sobre como as coisas acontecem, e não culpamos você, entendemos o que impulsiona este projeto

mas se olharmos do nosso ângulo, deve haver alguém para culpar, porque deixar questões como essa por anos apenas coletando polegares para cima é o que deixa de ser mais produtivo

tenho certeza de que há razões para adiar e focar em outras coisas primeiro, então acho que seria melhor se você deixasse seu público saber por que certos recursos altamente desejados não podem ser atendidos, isso pode diminuir o grau de frustração, digamos:

  • não podemos implementar esse recurso por causa de A, BC e esses precisam de D, E e F feitos primeiro

então acho que estou me referindo a esta conversa: https://github.com/Microsoft/TypeScript/issues/30696#issuecomment -478799258

A aprovação não cria novos recursos do nada, torna simples e fáceis decisões complexas e difíceis, altera as prioridades de negócios existentes, interrompe projetos em andamento, prioriza outros trabalhos, faz com que propostas excessivamente ambiciosas se tornem bem definidas ou alterar uma sugestão com impactos abrangentes e permanentes para se tornar focada e sustentável.

Eu não tenho desculpas por nós fazermos (ou permitir PRs para , que é o que você estava reclamando em #30696) trabalho bom e simples bem entendido antes de um trabalho extremamente complexo e de alta manutenção como este. Não deve ser difícil adivinhar por que estamos dispostos a deixar alguém entrar e consertar uma torneira pingando enquanto os planos de reformar o porão e adicionar outro andar em cima da casa ainda estão sendo elaborados.

@zpdDG4gta8XKpMCd Por que você precisa culpar alguém? Por que você não se culpa em primeiro lugar por não ter feito um PR para resolver esse problema? Ou pelo menos algum artigo construtivo sobre como abordá-lo do ponto de vista da implementação?

Oh cara, mesmo depois daquela escrita transparente que você acabou de ligar, você decidiu cutucar o urso novamente depois de apenas 2 semanas? Tente imaginar estar nessa posição com mais de 1500 tarefas em mãos e você precisa escolher algumas delas. Em nossa equipe, estamos movendo cerca de 100 tarefas e lutando bastante. Não consigo imaginar que seria 15 vezes mais 😮

@FredyC pelo amor de Deus, veja minha solução antes de dizer que não estou fazendo nada

sim, não estou fazendo pull requests formais porque:

  1. eu não estou no nível para fazer um bom

  2. para os simples, há uma longa fila de aprovação, e é preciso um tremendo trabalho para manter um pull request criado há 2 anos atualizado com a base de código atual, não tenho muito tempo

  3. certos problemas nem serão considerados, dadas as grandes considerações de design das quais apenas algumas pessoas como anders hejlsberg conhecem

você não pode tirar a parte da frustração, e eu não estou sozinho aqui

sabemos que existem esses fatores em jogo:

  • grande projeto da linguagem
  • orçamento / recursos / política dentro do MS
  • desejos da comunidade

eu ficaria mais feliz se a tomada de decisão com a mistura desses ingredientes fosse um pouco mais clara

eu terminei, foi longe demais, desculpe a todos cujos sentimentos foram feridos, não direi uma palavra

continuação de https://github.com/Microsoft/TypeScript/issues/14419#issuecomment -483920640

outra opção é usar as próprias declarações de função como marcadores, o que está abaixo é uma implementação de um gerador de código para funções cujos nomes começam com toRandom...

a fonte de informação para o gerador é o tipo de resultado da função

é assim que funciona:

  1. observe a linha ondulada em uma função que começa com toRandom...
    image
  2. explore suas opções:
    image
  3. faça uma correção rápida
    image
  4. observe os resultados:
    image

aqui está o código de codeGenRule.ts que faz isso

como um bônus, esta implementação só levantará um problema de linting se o código atual da função não corresponder ao código que deveria ser gerado

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 Acredito que esse problema era mais sobre ter uma maneira mais fácil de conectar transformadores personalizados durante a emissão? Ex. especificando transformações em tsconfig.json para que possam ser usadas com tsc em vez de usar a api . Você deseja alterações/correções de código personalizado no editor?

Eu não os usei, mas acho que o que você está falando já pode ser possível com um plug-in de serviço de idioma (acho que substituindo getCodeFixesAtPosition no serviço de idioma e inserindo suas próprias ações de código ... não tenho certeza) https://github.com/Microsoft/TypeScript/wiki/Writing-a-Language-Service-Plugin

Ou talvez eu esteja entendendo errado?

certo. isso é exatamente o que eu costumava pensar

eu pensei que uma maneira de especificar minhas transformações personalizadas via tsconfig.json seria um sonho tornado realidade

mas depois percebi que gosto ainda mais da minha solução alternativa

aqui está minha linha de pensamento:

  • eu precisava de um gerador de código configurável plugável
  • datilografado não tem nada assim à mão
  • por outro lado eu sei que o tslint (apesar de estar depreciado até o final de 2019) é uma plataforma de plugins decente para datilografar que tem uma forma de plugin e configurar seu código com muita liberdade
  • Acontece que tem tudo que eu preciso:

    • conectável e configurável

    • com toda a IU necessária

    • me dá uma API para datilografar

    • tem alguns extras

dado tudo isso, não consigo me ver escrevendo algo que use o serviço de linguagem datilografada, porque:

  • meu laptop só pode conter tantos serviços de linguagem datilografada, e alguns deles já são:

    • um dos vscode

    • um de tslint

e eu não quero adicionar outro em cima disso

eu gostaria de ter uma maneira melhor de conectar meus transformadores de código, mas temos o que temos


e é assim que fazemos macros: #4892

  • meu laptop só pode conter tantos serviços de linguagem datilografada, e alguns deles já são:

    • um por de vscode
    • um por tslint

@zpdDG4gta8XKpMCd Acredito que tudo deveria estar usando o mesmo serviço de idioma. Portanto, você terá um serviço de idioma único e, em seguida, o plug-in tslint junto com seu plug-in fará o proxy disso.

Btw, o que você está tentando fazer aqui deve ser definitivamente possível com um plugin de serviço de linguagem simples, porque é isso que é feito aqui .

De qualquer forma, vamos tentar manter a conversa aqui no tópico e apenas sobre transformadores personalizados como parte da compilação com tsc em vez de mudanças no código do editor/coisas de serviço de idioma. A maioria das pessoas está procurando uma solução para fazer uma transformação em um projeto inteiro e fazer isso dentro do editor não é uma solução viável (especialmente porque fazer uma transformação nesse ponto anula o propósito de usá-los). Idealmente, o que deve ser implementado aqui não deve ter nada a ver com o editor/tsserver ou serviço de linguagem.

obrigado pela valiosa contribuição, vou considerá-lo

discordo de você em manter a conversa apenas sobre transformadores personalizados como parte da compilação com tsc , já que

  • a solicitação original conforme escrita não é específica em qual forma as transformações devem ser entregues, apenas afirma que elas não devem exigir a necessidade de
    > duplique toda a linha de comando tsc apenas para adicionar um único transformador
  • ao longo de 2 anos esta discussão chamou bastante a atenção de muitas pessoas que não parecem se importar muito com a forma como os transformadores são implementados, desde que haja uma solução, funcione e seja fácil de usar
  • Além disso, a equipe do tslint fez um bom trabalho construindo a infraestrutura para plugins, não usá-la é um desperdício de esforço, desde que seja de fato a única plataforma oficialmente reconhecida fora do typescript que lida com typescript
  • Além disso, todos concordamos que, mesmo que os transformadores encontrem o caminho para o idioma, isso não acontecerá tão cedo, mas as pessoas aqui (inclusive eu) precisavam deles como ontem
  • por último, já que não existem muitas alternativas melhores, por que não consideramos pelo menos o que temos?

minha sugestão é claramente rotulada como uma solução alternativa (enquanto a equipe de design está dedicando seu tempo para pensar mais em uma solução adequada), então por que não?

se você insistir que devemos fazê-lo em outro lugar, por favor, fale

mas para abordar a sua preocupação de fazer um

transformar em um projeto inteiro

tslint faz exatamente isso com seu argumento --fix para cli

@zpdDG4gta8XKpMCd --fix atualizará o código TypeScript no local. Este problema é sobre fazer transformações durante a emissão (para que as alterações acabem apenas nos arquivos JavaScript finais). Veja o PR da edição referenciada (#13940):

Desde que o #13764 chegou, é fácil escrever transformadores personalizados. No entanto, se eu entendi a API corretamente, é necessário duplicar toda a linha de comando tsc apenas para adicionar um único transformador. Isso leva a incompatibilidades, pois esses aplicativos, dependendo do texto datilografado, não suportam os mesmos recursos que a ferramenta de linha de comando tsc.

Em outras palavras, esse problema trouxe CustomTransformers (clique nesse link e veja onde ele é usado na API), mas para usá-los tsc precisa ser duplicado de alguma forma ou encapsulado, que é o que ttypescript faz. O segundo parágrafo então fala sobre como isso seria bom porque se integraria bem nas ferramentas de construção existentes (já que obter os transformadores personalizados para usar seria tratado pelo tsc em vez de ferramentas de construção diferentes fazendo isso de maneiras diferentes).

Acho que seria mais produtivo abrir um novo problema com suas preocupações com correções de código ou querer uma maneira mais fácil de gerar código TypeScript dentro do código TypeScript. Não tenho certeza exatamente quais são essas preocupações, pois acho que muito disso já é possível hoje, mas o que você está discutindo é como fazer correções/ações de código, o que me parece um assunto não relacionado.

Acho que as principais perguntas a serem respondidas neste tópico são o que Daniel discutiu - "talvez haja algo mais amplo do que apenas pré e pós-transformadores" - e como seria a solução para fazer essa parte da construção.

você é vago

sou uma pessoa que entende e aprecia coisas simples

meu problema é que estou lidando com um projeto de mais de 3500 arquivos, dos quais 15% não precisam ser escritos e mantidos manualmente e há cerca de 5% de coisas semelhantes em cima dele por vir

ao mesmo tempo, sei que existe uma API que pode fazer isso por mim, mas é tão incompleta que nunca posso justificar meu tempo lidando com isso para deixá-lo totalmente pronto

então quando eu vim aqui eu pensei que este é o lugar certo para falar sobre isso, e acontece que pode haver uma solução rápida e simples

má sorte algumas pessoas que vieram aqui estão para discutir alguns assuntos muito mais delicados

ok, excelente!

e não, não vou abrir um novo problema apenas para mostrar às pessoas mais uma vez como o tslint pode resolver um dos principais problemas, fiz meu trabalho, estou pronto

Ter transformações configuráveis ​​prontas para uso seria bom. Estou tentando resolver um problema de string no código l10n e i18n . Posso alavancar ferramentas como tslint com uma regra personalizada para extração, mas minhas opções de transformar o código são limitadas, a menos que eu use algo como ttypescript , mas isso é problemático porque o aplicativo que estou trabalhando é um aplicativo angular não ejetado. Apenas me força a adicionar camadas sobre camadas de ferramentas de construção. Com o ritmo de desenvolvimento, toda a pilha se torna realmente precária.

Atualmente estamos desenvolvendo um framework e atualmente estamos usando ttypescript para acessar informações de nível de tipo em tempo de execução, seria bom ter a opção plugins no compilador oficial eventualmente 😄

Estou de férias agora, mas vou olhar semana que vem quando voltar

No domingo, 21 de julho de 2019 às 17h54 Giorgio Boa [email protected]
escrevi:

@longlho https://github.com/longlho Você criou um monte de grandes ast
transformadores, preciso de sua ajuda por favor 👍
Eu realmente gostaria de modificar os metadados do decorador antes da compilação Angular.
Meu objetivo é modificar este nó
Component({ selector: 'standard' ... }) into Component({ selector: 'custom'
... })
Eu fiz um repositório do github para testar
https://github.com/gioboa/ng-ts-transformer . acho que é possivel mas
sem documentação eu preciso de alguma ajuda. 🙏 Obrigado.


Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/microsoft/TypeScript/issues/14419?email_source=notifications&email_token=AABQM335QEEDNVT4NUICJQDQASBDXA5CNFSM4DCFER5KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2OGIWQissue#comment-513
ou silenciar o thread
https://github.com/notifications/unsubscribe-auth/AABQM33S5IYXB5HOZTRVVX3QASBDXANCNFSM4DCFER5A
.

Contribuí para criar uma biblioteca para criar mocks reais de interfaces sem proxy. Estou recomendando usar o ttypescript por enquanto, mas seria bom ter uma maneira de integração com o typescript

Eu realmente adoraria ver esse recurso acontecer. Tenho certeza de que essa é a única coisa entre o Typescript e algumas das maiores inovações que ele pode levar.

Typescript é uma grande contribuição para o desenvolvimento de front-end, mas também tem um freio em novas inovações…
Não quebre a semântica. Nenhum plugin ATM não pode quebrar a semântica; e nenhum plugin é permitido :man_shrugging: Por quê?
Existem plugins muito bons, mas. Todo plugin deve respeitar tokenização de palavras (chave) e instation AST)… , maneira muito difícil de fazer algo dentro.
Não é tão difícil. Não é fácil, mas o projeto babel mostra que é possível.
Na verdade, é quase trivial para o babel introduzir novas frases semânticas ou mesmo sintáticas.

Não espero que o texto datilografado permita a semântica. (também não estou esperando mudanças de sintaxe, é claro!)
O que eu desejo é que o compilador mude em alguns casos, como (pode ser apenas tipo) preeval.
Como se eu tivesse uma função take, como route ou message ou algo assim, o compilador pode avaliar e (oh, por favor, na fase um) verificar a correção.

Se você está lendo meu parágrafo anterior estranho. O que é tsx e todas as bondades do React?

Sem React, sem fluxo, sem texto datilografado, quase não de relance.

Por favor. Estou entendendo bem o olhar atento a tudo isso; mas como aprendemos com o IE5.5+; o bloqueio não é um caminho a seguir.

Se algo precisa ser melhorado, ainda é motor de layout. D.Knuth foi guenie que projetou todas as peças que faltavam 50 anos atrás. Por que não temos isso hoje?? :-)
Por favor, diga às pessoas para parar o CSS na maldade do JS.

Por favor. Open TS para inteligência semântica ; como função com entrada de string estática, fornecendo dica de tipo para o resto; analise a string de entrada const real…
Um Pequeno Exemplo:

  • Forma de retorno de chamada do GraphQL
  • Formato de entrada internacional
  • …muito mais_
    Por favor. Não são necessárias alterações semânticas. Tudo funcionará como desejado. Algo mais pode ser verificado em tempo de construção. Isso é tudo, pessoal! :Coelho:

ressalto

Estou experimentando escrever transformações TS para otimização core-js import - polyfilling automático para ambientes de destino, como @babel/preset-env e @babel/runtime , mas sem babel . Poderia ajudar seriamente uma grande parte dos desenvolvedores de TS. Mas sem suporte a transformações personalizadas da caixa sem ferramentas adicionais como ttypescript , a possibilidade de usar essas transformações será seriamente limitada, então não tenho certeza se faz sentido.

Eu tenho experimentado essa ideia - https://github.com/webschik/typescript-polyfills-generator.
Acho que a API do Transformers abrirá a possibilidade de retirar babel da cadeia de desenvolvimento. Acho que muitos desenvolvedores não querem usar os dois, mas ainda precisam de plugins como @babel/preset-env .

Atualmente, lançamos nosso próprio script de compilador personalizado (usando a API do compilador TypeScript) devido a essa limitação. Examinamos brevemente o ttypescript , mas o desejo de se afastar do compilador TypeScript vanilla para uma extensão do compilador TypeScript simplesmente não existe.

Seria fantástico se os transformadores personalizados fossem suportados no tsconfig.json. É complicado escrever um script que simplesmente analisa o tsconfig, declara os transformadores e depois executa o compilador; ou, pior, tentar realmente reimplementar recursos fundamentais do compilador, como observar arquivos, em um script personalizado.

Outras pessoas têm ecoado esse sentimento, mas permitir a facilidade de integrar transformadores personalizados no compilador tiraria uma carga significativa da equipe de desenvolvimento do TypeScript e permitiria inovação e impulso adicional com essa linguagem da comunidade.

Um exemplo de ecossistema de plugins muito bem-sucedido é a comunidade de plugins do Serverless Framework. A equipe de desenvolvimento não consegue acompanhar a demanda por desenvolvimento de recursos, e os plugins permitem uma ótima maneira de permitir a integração de novos recursos (possivelmente experimentais) sem a necessidade de abrir PRs ou diluir o produto principal com recursos que podem ou podem não fornecem valor para a base de usuários mais ampla.

Estou construindo uma biblioteca e tenho decoradores nela que funcionam muito bem para mim e dos quais dependo. Percebi há algum tempo que os decoradores tornam minha biblioteca não abalável. Depois de analisar isso, cheguei à conclusão de que os transformadores poderiam me ajudar a transformar esses decoradores em código abalável na compilação. É lamentável que eu não possa defini-los no meu pipeline. Espero que você chegue a esse problema em breve, só queria deixar meus 2 centavos em um caso de uso em que seria muito útil.

No interesse de fazer com que o TypeScript suporte transformadores personalizados sem programas wrapper e instruções complicadas, escrevi uma ferramenta chamada ts-patch ( npm github )

Simplesmente instale o ts-patch (globalmente ou localmente) e execute ts-patch install para corrigir o texto datilografado. Você também pode especificar o diretório de instalação do typescript e/ou ativar a persistência, que mantém o patch se o TS for atualizado ou reinstalado. (detalhes: ts-patch /? )

A lógica do patch é baseada principalmente no ttypescript. (Muito obrigado ao excelente trabalho do cevek!) Ele foi escrito de uma maneira que pode ser facilmente adicionado ao processo de instalação do pacote npm. Também é fácil descompactar.

Para ser claro, isso corrige diretamente os arquivos relevantes no próprio texto datilografado e não é um wrapper. Basta executar o patch após a instalação da dependência e o typescript estará pronto para o transformador.

Espero que isso ajude algumas pessoas!

No interesse de fazer com que o TypeScript suporte transformadores personalizados sem programas wrapper e instruções complicadas, escrevi uma ferramenta chamada ts-patch ( npm github )

Simplesmente instale o ts-patch (globalmente ou localmente) e execute ts-patch install para corrigir o texto datilografado. Você também pode especificar o diretório de instalação do typescript e/ou ativar a persistência, que mantém o patch se o TS for atualizado ou reinstalado. (detalhes: ts-patch /? )

A lógica do patch é baseada principalmente no ttypescript. (Muito obrigado ao excelente trabalho do cevek!) Ele foi escrito de uma maneira que pode ser facilmente adicionado ao processo de instalação do pacote npm. Também é fácil descompactar.

Para ser claro, isso corrige diretamente os arquivos relevantes no próprio texto datilografado e não é um wrapper. Basta executar o patch após a instalação da dependência e o typescript estará pronto para o transformador.

Espero que isso ajude algumas pessoas!

isso poderia ser levantado como um PR para adicionar/discutir o suporte adequado? :)

Ei. Para o que vale a pena, há um empacotador chamado fuse-box que facilita muito a adição de transformadores personalizados. Sua versão 4.0 está chegando em breve... então está em um ponto intermediário. Mas no geral, eu realmente gosto do bundler. Talvez possa te ajudar também.

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

isso poderia ser levantado como um PR para adicionar/discutir o suporte adequado? :)

A equipe do TS expressou que não deseja fornecer isso como um recurso nativo. Suas razões para a decisão fazem sentido!

A boa notícia é que, como o TS é de código aberto e já é compilado de forma modular, o ts-patch se comporta de uma maneira muito parecida com o que aconteceria se estivesse embutido. Portanto, não é como um patch de bytecode de engenharia reversa com erros.

Se, pelo suporte, você estiver preocupado com a manutenção, pretendo mantê-lo atualizado e funcionando para todas as versões futuras do TS! Muito da minha infraestrutura comercial já depende disso.

Como nota lateral, lançarei uma nova versão em breve que permite empacotar vários plugins com diferentes pontos de entrada em um único pacote, bem como algumas outras otimizações para melhorá-lo e torná-lo mais fácil de usar.

Depois de escrever um plugin, posso entender por que a equipe ts está hesitante - o transformador de corrente é uma etapa pós-compilação. Você se depara com problemas desagradáveis ​​se fizer algo complicado e começar a adicionar novo conteúdo que não foi originalmente vinculado. Tal como está, ts-node --compiler ttypescript foo.ts funciona perfeitamente bem. Prefiro que a equipe ts lide com plugins de transformador em diferentes etapas de compilação... ou permita uma etapa de religação.

O transformador de corrente é uma etapa pós-compilação. Você se depara com problemas desagradáveis ​​se fizer algo complicado e começar a adicionar novo conteúdo que não foi originalmente vinculado.

Os transformadores podem ser executados antes ou depois da compilação do TSC. Parece que o que você pode estar se referindo é que o verificador não atualiza após modificar os nós. Isso pode realmente ser contornado, a funcionalidade simplesmente não foi criada para isso. Quando você invoca ts.transform(), ele não cria uma instância de programa completa para você trabalhar, então se você quiser trabalhar com o verificador, você precisa criar uma. Usando o CompilerHost, você pode recarregá-lo com os arquivos modificados após alterar o AST.

Ainda não fui muito longe nisso, mas parece que também pode ser possível usar a funcionalidade 'watch' para evitar ter que reconstruir toda a instância do programa a cada vez. Simplificando, acontece que não é _muito_ difícil ter um sistema de Plugin mais completo, mas transform simplesmente não tem o suporte em seu contexto fornecido.

@nonara Eu usei transformações com ttypescript e ts-loader`, ambos têm pontos de entrada de programa completos. Meu problema é que, se você adicionar uma nova instrução de importação, está faltando "algo" e essas novas instruções são removidas da emissão de saída final. @weswigham diz que é porque transform é uma etapa pós-vinculação . A solução aparentemente é criar um programa totalmente novo para o arquivo - mas isso parece uma dor de cabeça quando você está lidando com coisas como ts-loader (especialmente quando está no modo somente transformação e oculta completamente o arquivo webpack/bundler- No final eu larguei a importação e apenas inline o código que eu precisava .

@MeirionHughes Ah, ok. Nesse caso, sim, você tem uma instância do programa. ttypescript funciona conectando createProgram para corrigir o método emit do program resultante para incluir os transformadores.

  • ts.emitFiles chama ts.transformNodes durante o processo.
  • ts.transformNodes pode ser chamado com ou sem uma instância do programa. Chamar diretamente ts.transform() faz isso sem um.

Se estou entendendo corretamente, parece que seu problema também está relacionado ao fato de que os tipos e símbolos já foram percorridos e não são atualizados após a transformação AST.

Olá a todos, estou escrevendo um Manual do Transformer para colocar todas as informações sobre os transformadores, bem como para facilitar o início.

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

Adoraria alguns olhos nele se você puder poupar um segundo 👍

@madou Eu também escrevi vários posts sobre transformadores TS https://levelup.gitconnected.com/writing-typescript-custom-ast-transformer-part-1-7585d6916819

Qual é o status disso?

Amo muito o texto datilografado, mas parece especialmente desajeitado quando você começa a interoperar entre tipos estáticos e JS de tempo de execução. Existem vários plugins escritos pela comunidade para melhorar isso, por exemplo, https://github.com/dsherret/ts-nameof , https://github.com/kimamula/ts-transformer-keys - mas sem suporte de plugin de primeira classe parece uma decisão técnica arriscada incluí-los em um projeto. Habilitar plugins nativamente permitiria que a comunidade brinque com potenciais futuros recursos datilografados, antes que eles precisem ser incluídos na biblioteca principal.

Acho que a equipe do TypeScript deveria reconsiderar sua argumentação. O ecossistema de plugins é uma maneira comprovada de levar a linguagem adiante, permitindo (e encorajando) experimentos (veja Haskell com seus pragmas).

Alguns desses experimentos serão selvagens e malucos, e alguns eventualmente se estabilizarão e se tornarão comuns. É sempre bom fornecer a capacidade de implementar recursos de linguagem no espaço do usuário.

Em geral, a posição da equipe do TypeScript parece desnecessária e rígida.

Há também transformações que não alteram o idioma, mas fornecem informações adicionais para facilitar a depuração.

Por exemplo, o babel-plugin-transform-react-jsx-source faz parte da predefinição de transpilação de reação padrão ( @babel/preset- react ).
Ele transforma

<sometag />

Para dentro

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

Essas informações permitem que react forneça melhores rastreamentos de pilha de erros durante o desenvolvimento.

Para texto datilografado, não há uma maneira padrão de obter o mesmo, embora haja uma transformação de código aberto: https://github.com/dropbox/ts-transform-react-jsx-source

Eu entendo que @mhegazy mencionou duas vezes que a equipe TS não tem planos de incluir “plugins” como parte do tsconfig. Qual é o raciocínio por trás disso?

Você estaria aberto a um PR? A maneira como o ttypescript lida com os transformadores via tsconfig é bem legal.

Casos de uso:

1) gerar tipos de interface para esquemas para que possam ser verificados em tempo de execução.
2) importar json com strings como literais para que o typescript não vomite quando atribuído a um tipo com uniões discriminadas.
3) importando css/yaml e outro objeto como sintaxe
4) fazer consultas graphql que criam dinamicamente os tipos certos
5) compilando jsx para strings html para que possam ser injetadas innerHTML
5) reescrever importações absolutas para importações relativas com base em caminhos tsconfig.

A lista continua e continua. A API do plugin é boa. Obrigado por aterrissar. Ter “plugins” como parte do “tsconfig” torna o tsc realmente poderoso. Há algo grande que estamos perdendo?

você também pode fazer muitas otimizações de desempenho. eu tenho escrito https://github.com/atlassian-labs/compiled-css-in-js com transformadores datilografados 🤙 seria legal se os consumidores não precisassem passar por aros para usá-lo.

Querida equipe Typescript, por favor, pare de se arrastar com isso <_<

Qual é o status disso?

Status?

Amigos que novidades?

A equipe do typescript decidiu contra essa ideia - se você precisar de flexibilidade ou melhores ferramentas de desenvolvimento, usar o typescript não é uma opção sem hacks - vá com o babel e use o typescript apenas para verificação de digitação

A equipe do typescript decidiu contra essa ideia - se você precisar de flexibilidade ou melhores ferramentas de desenvolvimento, usar o typescript não é uma opção sem hacks - vá com o babel e use o typescript apenas para verificação de digitação

Mas e se eu quiser alguns hacks para verificação de tipos? Eu escrevo um pequeno transformador que faz alguma mágica:

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

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

Função check transformada em função específica de proteção de tipo! Como posso fazer isso com Babel? Atualmente, devo usar ttypescript ...

A equipe do typescript decidiu contra essa ideia - se você precisar de flexibilidade ou melhores ferramentas de desenvolvimento, usar o typescript não é uma opção sem hacks - vá com o babel e use o typescript apenas para verificação de digitação

Na verdade, há alguma conversa sobre isso se tornar suportado no futuro. Dito isto, ele realmente já é suportado. A API do compilador TypeScript oferece suporte a transformadores e é _realmente_ simples escrever um compilador personalizado que usa transformadores em apenas algumas linhas de código.

Mas para facilitar, você pode usar ttypescript ou ts-patch .

Essas bibliotecas não são realmente "hacks" no sentido de que não estão aumentando o compilador para adicionar capacidade de transformador. Em vez disso, eles simplesmente expõem a funcionalidade existente da API do compilador para tsc , tornando-a utilizável via tsconfig.

@ilya-buligin se eu entendi seu caso de uso corretamente, você pode declarar uma constante de ambiente

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

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

O Typescript compilará o código com base na definição de tipo check e, em seguida, você o substituirá por um código gerado usando o Babel.

@just-boris como posso obter acesso ao tipo genérico <T> no Babel?

Este tópico está ficando bastante repetitivo e fora do tópico. @RyanCavanaugh Talvez este tópico deva ser bloqueado, até que você tenha atualizações sobre o assunto.

Esta página foi útil?
0 / 5 - 0 avaliações