Desempenho do TypeScript



Existem maneiras fáceis de configurar o TypeScript para acelerar a compilação e a edição. E quanto mais cedo eles forem implementados, melhor. Existem também algumas abordagens populares para investigar as causas da compilação e edição lentas, algumas correções e maneiras comuns de ajudar a equipe do TypeScript a investigar os problemas.



1. Escrevendo código fácil de compilar



1.1. Preferir interfaces em vez de interseções (interseção)



Na maioria das vezes, um alias simples para um tipo de objeto age da mesma maneira que uma interface.



interface Foo { prop: string }

type Bar = { prop: string };

      
      





Mas se você precisar de uma combinação de dois ou mais tipos, pode estendê-los usando uma interface ou criar uma interseção de tipos em um alias. A diferença entre essas abordagens é importante.



As interfaces criam um único tipo de objeto achatado que expõe conflitos de propriedade que geralmente são importantes para resolver! E as interseções simplesmente combinam propriedades recursivamente e, em alguns casos, geram never



... Além disso, as interfaces são renderizadas melhor, enquanto aliases de tipo para interseções não podem ser exibidos em outras interseções. Os relacionamentos de tipo entre as interfaces são armazenados em cache, ao contrário dos tipos de interseção. A diferença importante final é que ao validar em relação a um tipo de interseção de destino, cada componente é validado antes de ser validado / nivelado.



Portanto, é recomendado estender os tipos com interface



/ em extends



vez de criar interseções de tipo.



- type Foo = Bar & Baz & {
-     someProp: string;
- }
+ interface Foo extends Bar, Baz {
+     someProp: string;
+ }

      
      





1.2. Usando anotações de tipo



Adicionar anotações de tipo, especialmente para valores de retorno, pode economizar muito trabalho para o compilador. Em parte, isso ocorre porque os tipos nomeados geralmente são mais compactos do que os anônimos (que o compilador pode lançar), o que reduz o tempo que leva para ler e gravar os arquivos de declaração (por exemplo, para compilações incrementais). A fundição é muito conveniente, portanto, não há necessidade de fazê-lo universalmente. Mas pode ser útil tentar ao encontrar fragmentos lentos em seu código.



- import { otherFunc } from "other";
+ import { otherFunc, otherType } from "other";

- export function func() {
+ export function func(): otherType {
      return otherFunc();
  }

      
      





1.3. Preferência por tipos de base sobre vários tipos



Vários tipos são uma ótima ferramenta: eles permitem que você expresse a gama de valores possíveis para um tipo.



interface WeekdaySchedule {
  day: "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday";
  wake: Time;
  startWork: Time;
  endWork: Time;
  sleep: Time;
}

interface WeekendSchedule {
  day: "Saturday" | "Sunday";
  wake: Time;
  familyMeal: Time;
  sleep: Time;
}

declare function printSchedule(schedule: WeekdaySchedule | WeekendSchedule);

      
      





Mas tudo tem um preço. Cada vez que um argumento é passado para printSchedule



ele, ele deve ser comparado com cada elemento do conjunto. Isso não é um problema para dois elementos. Mas se houver uma dúzia de elementos no conjunto, isso pode diminuir a velocidade de compilação. Por exemplo, para remover elementos redundantes, todos eles precisam ser comparados em pares, esta é uma função quadrática. Essas verificações podem ocorrer durante a interseção de conjuntos grandes, quando a interseção de cada elemento do conjunto pode levar a tipos enormes que precisam ser reduzidos. E você pode evitar tudo isso usando subtipos, não conjuntos.



interface Schedule {
  day: "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | "Sunday";
  wake: Time;
  sleep: Time;
}

interface WeekdaySchedule extends Schedule {
  day: "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday";
  startWork: Time;
  endWork: Time;
}

interface WeekendSchedule extends Schedule {
  day: "Saturday" | "Sunday";
  familyMeal: Time;
}

declare function printSchedule(schedule: Schedule);

      
      





Um exemplo mais realista é ao tentar modelar todos os tipos de elementos DOM integrados. Nesse caso, é preferível criar um tipo de base HtmlElement



com elementos frequentes, que se expandem com DivElement



, ImgElement



etc., em vez de criar um conjunto pesado DivElement | /*...*/ | ImgElement | /*...*/



.



2. Usando links de projeto



Ao construir qualquer grande base de código TypeScript, é útil organizá-lo em vários projetos independentes . Cada um deles tem suas próprias tsconfig.json



dependências em outros projetos. Isso pode ajudar a evitar o download de muitos arquivos em uma compilação e também pode facilitar a combinação de diferentes esquemas de base de código.



Existem algumas maneiras muito simples de dividir sua base de código em projetos . Por exemplo, um projeto para um cliente, um projeto para um servidor e um projeto comum entre eles.



             ------------
              |          |
              |  Shared  |
              ^----------^
             /            \
            /              \
------------                ------------
|          |                |          |
|  Client  |                |  Server  |
-----^------                ------^-----

      
      





Os testes também podem ser separados em um projeto separado.



             ------------
              |          |
              |  Shared  |
              ^-----^----^
             /      |     \
            /       |      \
------------  ------------  ------------
|          |  |  Shared  |  |          |
|  Client  |  |  Tests   |  |  Server  |
-----^------  ------------  ------^-----
     |                            |
     |                            |
------------                ------------
|  Client  |                |  Server  |
|  Tests   |                |  Tests   |
------------                ------------

      
      





As pessoas costumam perguntar: "Qual deve ser o tamanho do projeto?" É como perguntar: "Qual deve ser o tamanho de uma função?" ou "Qual deve ser o tamanho da classe?" Muito depende da experiência. Digamos que você possa compartilhar o código JS / TS usando pastas e, se alguns componentes estiverem interconectados o suficiente para serem colocados em uma pasta, você pode considerá-los pertencentes ao mesmo projeto. Além disso, evite projetos grandes ou pequenos. Se um deles for maior do que todos os outros combinados, isso é um mau sinal. Também é melhor não criar dezenas de projetos de arquivo único, pois isso aumenta a sobrecarga.



Você pode ler sobre links de projetos cruzados aqui .



3. Configurando tsconfig.json ou jsconfig.json



Os usuários de TypeScript e JavaScript sempre podem personalizar suas compilações usando o arquivo tsconfig.json. Os arquivos Jsconfig.json também podem ser usados para personalizar a edição de JavaScript .



3.1. Definindo arquivos



Sempre certifique-se de que seus arquivos de configuração não listem muitos arquivos de uma vez.



Você tsconfig.json



pode definir arquivos de projeto de duas maneiras:



  • lista files



    ;
  • listas include



    e exclude



    ;


A principal diferença entre os dois é que ele files



obtém uma lista de caminhos de arquivo de origem e include



/ exclude



usa padrões de globbing para identificar os arquivos correspondentes.



Ao definir files



, permitimos que o TypeScript carregue rapidamente os arquivos diretamente. Isso pode ser complicado se o projeto tiver muitos arquivos e apenas alguns pontos de entrada de alto nível. Também é fácil esquecer de adicionar novos arquivos e tsconfig.json



, então, você se depara com um comportamento estranho do editor.



include



/ exclude



não exige que todos esses arquivos sejam identificados, mas o sistema deve detectá-los examinando os diretórios adicionados. E se houver muitos, a compilação pode ficar mais lenta. Além disso, às vezes vários .d.ts



arquivos desnecessários e de teste são incluídos na compilação , o que também pode reduzir a velocidade e aumentar o consumo de memória. Finalmente, embora exclude



existam padrões adequados, algumas configurações como repositórios mono têm pastas "pesadas" como node_modules



aquelas que serão adicionadas em tempo de compilação.



É melhor fazer isso:



  • Defina apenas as pastas de entrada de seu projeto (por exemplo, o código-fonte do qual você deseja adicionar durante a compilação e análise).
  • Não misture arquivos de origem de projetos diferentes na mesma pasta.
  • Se você armazenar testes na mesma pasta de origem, nomeie-os de forma que possam ser facilmente excluídos.
  • Evite criar grandes artefatos de montagem e pastas de dependência como node_modules



    .


Nota: Sem uma lista, a exclude



pasta node_modules



será excluída por padrão. E se a lista for adicionada, é importante indicar explicitamente nela node_modules



.



Aqui está um exemplo tsconfig.json



:



{
    "compilerOptions": {
        // ...
    },
    "include": ["src"],
    "exclude": ["**/node_modules", "**/.*/"],
}

      
      





3.2. Controle sobre a adição de @types



Por padrão, o TypeScript adiciona automaticamente todos os node_modules



pacotes encontrados em uma pasta @types



, importados ou não. Isso é para fazer certas funções “simplesmente funcionarem” ao usar Node.js, Jasmine, Mocha, Chai, etc., uma vez que essas ferramentas / pacotes não são importados, mas carregados no ambiente global.



Às vezes, essa lógica pode retardar a compilação e edição do programa. E ainda levam a conflitos de declaração em vários pacotes globais que causam erros como este:



Duplicate identifier 'IteratorResult'.
Duplicate identifier 'it'.
Duplicate identifier 'define'.
Duplicate identifier 'require'.

      
      





Se os pacotes globais não forem necessários, você pode definir uma pasta vazia na opção "tipos" em tsconfig.json



/ jsconfig.json



:



// src/tsconfig.json
{
   "compilerOptions": {
       // ...

       // Don't automatically include anything.
       // Only include `@types` packages that we need to import.
       "types" : []
   },
   "files": ["foo.ts"]
}

      
      





Se você precisar de pacotes globais, adicione-os ao campo types



.



// tests/tsconfig.json
{
   "compilerOptions": {
       // ...

       // Only include `@types/node` and `@types/mocha`.
       "types" : ["node", "mocha"]
   },
   "files": ["foo.test.ts"]
}

      
      





3.3. Geração de projeto incremental



O sinalizador --incremental



permite que o TypeScript salve o último estado compilado em um arquivo .tsbuildinfo



. É usado para definir o conjunto mínimo de arquivos que podem ser verificados novamente / sobrescritos desde a última execução, como o modo --watch



no TypeScript.



A geração incremental é habilitada por padrão ao usar o sinalizador de composite



referência de projeto cruzado , mas também pode acelerar qualquer outro projeto.



3.4. Ignorando validação .d.ts



Por padrão, o TypeScript verificará novamente todos os .d.ts



arquivos em um projeto para encontrar problemas e inconsistências. Mas isso geralmente não é necessário. Na maioria das vezes, esses arquivos já funcionam: os métodos de expansão de tipo já foram verificados, mas as declarações importantes ainda serão verificadas.



TypeScript permite que um sinalizador skipDefaultLibCheck



ignore a verificação de tipo nos .d.ts



arquivos fornecidos (por exemplo, in lib.d.ts



).



Você também pode ativar o sinalizador skipLibCheck



para ignorar a verificação de todos os .d.ts



arquivos na compilação.



Essas duas opções muitas vezes escondem erros de configuração e conflitos em .d.ts



arquivos, por isso é recomendado usá-los apenas para acelerar a compilação.



3,5. Verificações variáveis ​​mais rápidas



Lista de cães ou animais? Você pode levar List<Dg>



a List<Animls>



? Uma maneira fácil de encontrar a resposta é comparar estruturalmente os tipos, elemento por elemento. Infelizmente, essa solução pode ser muito cara. Mas, se soubermos o suficiente sobre List<>



, podemos reduzir as verificações de atribuição para determinar se é permitido fazer referência Dog



a Animal



(isto é, sem verificar cada elemento List<>



). Em particular, precisamos saber a variabilidade do tipo de parâmetro T



. O compilador pode tirar total vantagem da otimização apenas se o sinalizador estiver ativado strictFunctionTypes



(caso contrário, ele usará uma verificação estrutural mais lenta, porém mais branda). Portanto, é recomendável construir com o sinalizador --strictFunctionTypes



(que é habilitado por padrão em --strict



).



4. Configurando outras ferramentas de montagem



O TypeScript é frequentemente compilado com outras ferramentas de construção, especialmente ao construir um aplicativo da web que pode usar o bundler. Podemos oferecer apenas algumas idéias, mas em geral essa abordagem pode ser generalizada.



Além desta parte, certifique-se de ler sobre o desempenho da ferramenta escolhida, por exemplo:





4.1.



A verificação de tipo geralmente requer informações de outros arquivos e é relativamente cara em comparação com outras etapas, como conversão / gravação de código. Como a verificação de tipo pode consumir muito tempo, ela pode afetar o ciclo de desenvolvimento interno. Ou seja, o ciclo de edição-compilação-execução ficará mais longo, o que é desagradável.



Portanto, muitas ferramentas de construção podem verificar os tipos em um processo separado, sem bloquear a criação do arquivo. Embora, nesse caso, o código incorreto possa ser executado antes que o TypeScript relate o erro em sua ferramenta de construção. Na maioria das vezes, você verá erros no editor primeiro e não aguardará a execução do código.



Um exemplo é o fork-ts-checker-webpack-pluginpara Webpack, ou um semelhante incrível-typescript-loader .



4.2. Criação de arquivo isolado



Por padrão, a criação de arquivos em TypeScript requer informações semânticas que podem não ser locais para o arquivo. Isso é necessário para entender como os recursos são semelhantes const enum



e gerados namespace



. Mas às vezes a geração fica mais lenta devido à necessidade de verificar outros arquivos para gerar o resultado de um arquivo arbitrário.



Raramente precisamos de recursos que requeiram informações não locais. Regulars enum



podem ser usados ​​em seu lugar const enum



e módulos podem ser usados namespace



. Portanto, o TypeScript tem um sinalizador isolatedModules



para emitir erros em recursos que requerem informações não locais. Com este sinalizador, você pode usar com segurança ferramentas que usam APIs TypeScript como transpileModule



ou compiladores alternativos como Babel.



Este código não funcionará corretamente em tempo de execução com a conversão de arquivo em área restrita porque os valores devem ser embutidos const enum



. Felizmente, ele nos isolatedModules



avisará com antecedência.



// ./src/fileA.ts

export declare const enum E {
    A = 0,
    B = 1,
}

// ./src/fileB.ts

import { E } from "./fileA";

console.log(E.A);
//          ~
// error: Cannot access ambient const enums when the '--isolatedModules' flag is provided.

      
      





Lembre-se: isolatedModules



não acelera automaticamente a geração de código. Ele apenas avisa sobre o uso de um recurso que pode não ser compatível. Você precisa gerar módulos isolados em diferentes ferramentas de construção e APIs.



Você pode criar arquivos isoladamente usando as seguintes ferramentas:





5. Investigação do problema



Existem diferentes maneiras de descobrir por que algo está errado.



5.1. Desativar plug-ins do editor



Os plug-ins podem afetar o funcionamento do editor. Tente desativá-los (especialmente os relacionados a JavaScript / TypeScript) e veja se o desempenho e a capacidade de resposta melhoram.



Alguns editores têm suas próprias recomendações de desempenho, leia-as. Por exemplo, o Visual Studio Code tem uma página de dicas separada .



5,2 ExtendedDiagnostics



Você pode executar o TypeScript --extendedDiagnostics



para ver onde o tempo do compilador é gasto:



Files:                         6
Lines:                     24906
Nodes:                    112200
Identifiers:               41097
Symbols:                   27972
Types:                      8298
Memory used:              77984K
Assignability cache size:  33123
Identity cache size:           2
Subtype cache size:            0
I/O Read time:             0.01s
Parse time:                0.44s
Program time:              0.45s
Bind time:                 0.21s
Check time:                1.07s
transformTime time:        0.01s
commentTime time:          0.00s
I/O Write time:            0.00s
printTime time:            0.01s
Emit time:                 0.01s
Total time:                1.75s

      
      





Observe que Total time



não será a soma de todos os custos de tempo listados, uma vez que alguns deles se sobrepõem e alguns não são medidos.



As informações mais relevantes para a maioria dos usuários:



Campo Valor
Files





O número de arquivos incluídos no programa (que tipo de arquivos você pode ver usando --listFiles



).
I/O Read time





Tempo gasto na leitura do sistema de arquivos. Isso inclui a leitura de pastas de include



.
Parse time





Tempo gasto digitalizando e analisando o programa.
Program time





O tempo total para leitura do sistema de arquivos, verificação e análise do programa, bem como outros cálculos gráficos. Esses estágios são combinados aqui porque eles precisam ser ativados e carregados assim que forem adicionados via import



e export



.
Bind time





Tempo gasto na montagem de várias informações semânticas locais para um arquivo específico.
Check time





O tempo gasto para verificar os tipos no programa.
transformTime time





Tempo gasto reescrevendo ASTs TypeScript (árvores que representam arquivos de origem) em formulários que funcionam em ambientes de tempo de execução legados.
commentTime





Tempo gasto avaliando comentários em arquivos gerados.
I/O Write time





Tempo gasto gravando e atualizando arquivos no disco.
printTime





O tempo gasto para calcular a representação de string do arquivo gerado e salvá-lo no disco.


Dadas essas entradas, o que você pode precisar:



  • O número de arquivos / linhas de código corresponde aproximadamente ao número de arquivos no projeto? Se não, tente usar --listFiles



    .
  • Valores Program time



    ou I/O Read time



    parecem grandes? Verifique se as configurações estão corretas include



    /exclude





Parece que há algo errado com os outros horários? Você pode preencher um relatório de problema! O que o ajudará a diagnosticar:



  • Comece com emitDeclarationOnly



    se o valor for printTime



    alto.
  • Instruções para relatórios de problemas de desempenho do compilador




5,3. showConfig



Nem sempre está claro com quais configurações a compilação é realizada na inicialização tsc



, especialmente considerando que tsconfig.jsons



outros arquivos de configuração podem ser estendidos. showConfig



pode explicar o que vai calcular tsc



.



tsc --showConfig

# or to select a specific config file...

tsc --showConfig -p tsconfig.json

      
      





5,4 traceResolution



Executar com traceResolution



o informará por que o arquivo foi adicionado à compilação. Os dados são bastante extensos, então você pode salvar o resultado em um arquivo:



tsc --traceResolution > resolution.txt

      
      





Se encontrar um arquivo que não deveria estar lá, você pode corrigir a lista include



/ exclude



no arquivo tsconfig.json



ou ajustar as configurações como types



, typeRoots



ou paths



.



5.5. Executando um tsc



Os usuários costumam ter um desempenho ruim com ferramentas de construção de terceiros, como Gulp, Rollup, Webpack, etc. A execução tsc --extendedDiagnostics



para encontrar grandes discrepâncias entre o TypeScript e uma ferramenta de terceiros pode indicar erros em configurações externas ou ineficiência.



O que você precisa se perguntar:



  • Existe uma grande diferença nos tempos de construção tsc



    com a ferramenta integrada TypeScript?
  • Se a ferramenta de terceiros tiver ferramentas de diagnóstico, a solução é diferente entre o TypeScript e a ferramenta de terceiros?
  • A ferramenta tem sua própria configuração que pode estar causando baixo desempenho?
  • A ferramenta tem uma configuração para integrá-la ao TypeScript que pode estar causando um desempenho ruim (como opções para ts-loader)?


5,6. Atualizando dependências



Às vezes, arquivos computacionalmente complexos podem afetar a verificação de tipo no TypeScript .d.ts



. Raramente, mas acontece. Isso geralmente é resolvido com a atualização para uma versão mais recente do TypeScript (mais eficiente) ou uma versão mais recente do pacote @types



(que poderia reverter a regressão).



6. Problemas frequentes



Ao se deparar com dificuldades, você desejará aprender sobre soluções para problemas comuns. Se o seguinte não ajudar, você pode relatar o problema .



6.1. Inclusão e exclusão configuradas incorretamente



Conforme mencionado, as opções include



/ exclude



podem ser mal utilizadas.



Problema Causa Correção
node_modules



foi adicionado acidentalmente de uma subpasta mais profunda.
Não foi configurado exclude



"exclude": ["**/node_modules", "**/.*/"]





node_modules



foi adicionado acidentalmente de uma subpasta mais profunda.
"exclude": ["node_modules"]





"exclude": ["**/node_modules", "**/.*/"]





Arquivos ocultos com um ponto são adicionados aleatoriamente (por exemplo .git



).
"exclude": ["**/node_modules"]





"exclude": ["**/node_modules", "**/.*/"]





Adicionados arquivos inesperados. Não foi configurado include



"include": ["src"]







7. Preenchimento de relatórios de problemas



Se o seu projeto já estiver configurado de forma correta e ideal, você pode preencher um relatório de problema .



Um bom relatório contém uma descrição fácil de seguir do problema. Ou seja, ele contém uma base de código de vários arquivos que podem ser facilmente clonados via Git. Nesse caso, não há necessidade de integração externa com ferramentas de montagem, elas podem ser chamadas tsc



ou você pode usar o código em área restrita que usa a API TypeScript. Você não pode priorizar bases de código que requerem chamadas e configurações complexas.



Sim, isso nem sempre é fácil de conseguir. Especialmente porque é difícil isolar a origem do problema dentro da base de código e também há considerações de proteção de propriedade intelectual. Em alguns casos, você pode nos enviar um NDA se achar que o problema é de grande importância.



Independentemente da reprodutibilidade do problema, ao preencher o relatório, siga estas dicas, elas nos ajudarão a encontrar uma solução.



7.1. Relatório de problemas de desempenho do compilador



Ocasionalmente, problemas de desempenho ocorrem durante a construção e edição. Então, faz sentido se concentrar no compilador TypeScript.



Primeiro, use a versão "noturna" do TypeScript para ter certeza de que não está encontrando um problema corrigido:



npm install --save-dev typescript@next

# or

yarn add typescript@next --dev

      
      





A descrição do problema de desempenho deve incluir:



  • Versão instalada do TypeScript ( npx tsc -v



    ou yarn tsc -v



    ).
  • A versão do Node em que TypeScript ( node -v



    ) estava sendo executado .
  • Resultado da execução com a opção extendedDiagnostics



    ( tsc --extendedDiagnostics -p tsconfig.json



    ).
  • Idealmente, o próprio projeto é necessário para demonstrar o problema em questão.
  • Log do compilador do compilador (arquivos isolate-*-*-*.log



    e *.cpuprofile



    ).


Perfil do compilador



É importante nos fornecer um rastreamento de diagnóstico executando Node.js v10 + com o sinalizador --trace-ic



e TypeScript com o sinalizador --generateCpuProfile



:



node --trace-ic ./node_modules/typescript/lib/tsc.js --generateCpuProfile profile.cpuprofile -p tsconfig.json

      
      





Isso ./node_modules/typescript/lib/tsc.js



pode ser substituído por qualquer caminho em que sua versão do compilador TypeScript esteja instalada. E, em vez disso, tsconfig.json



pode ser qualquer arquivo de configuração do TypeScript. Em vez disso profile.cpuprofile



- o arquivo de saída de sua escolha.



Dois arquivos serão gerados:



  • --trace-ic



    salvará os dados em um arquivo de visualização isolate-*-*-*.log



    (por exemplo isolate-00000176DB2DF130-17676-v8.log



    ).
  • --generateCpuProfile



    salvará os dados em um arquivo com um nome de sua escolha. No exemplo acima, é profile.cpuprofile



    .


Aviso : esses arquivos podem conter informações do seu espaço de trabalho, incluindo caminhos e código-fonte. Ambos os arquivos são criados em texto simples e você pode editá-los antes de anexá-los ao relatório do Github (por exemplo, limpando caminhos que podem revelar informações confidenciais).



Mas se você tiver alguma dúvida sobre como colocá-los no Github, escreva para nós, e você poderá enviar as informações em particular.



7.2. Problemas de desempenho do editor de relatórios



Existem muitos motivos para um desempenho de edição ruim. E a equipe do TypeScript só pode afetar o desempenho do serviço de linguagem JavaScript / TypeScript, bem como a integração entre o serviço de linguagem e certos editores (por exemplo, Visual Studio, Visual Studio Code, Visual Studio para Mac e Sublime Text). Certifique-se de que todos os plug-ins de terceiros estejam desativados em seu editor. Isso verificará se o problema está relacionado ao próprio TypeScript.



Os problemas de desempenho do editor são um pouco mais complexos, mas as mesmas ideias se aplicam: bases de código mínimas clonadas com um problema reproduzível são ideais. E, em alguns casos, podemos assinar um NDA para investigar e isolar os problemas.



Adicionando dados de tsc --extendedDiagnostics



, mas ainda melhor se houver um rastreamento do TSServer.



Obtendo logs do TSServer no Visual Studio Code



  1. Abra a barra de comando e:
  2. Defina a opção «typescript.tsserver.log»: «verbose»,



    .
  3. Reinicie o VS Code e reproduza o problema.
  4. No VS Code, execute o comando TypeScript: Open TS Server log



    .
  5. O arquivo deve abrir tsserver.log



    .


Observação : o log do TSServer pode conter informações do seu espaço de trabalho, incluindo caminhos e código-fonte. Se você tiver alguma dúvida sobre como colocá-lo no Github, escreva para nós e poderá enviar as informações em particular.



All Articles