Typechecking after running Typescript compiler plugin/transformer





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







1















I'm following a blog (https://dev.doctorevidence.com/how-to-write-a-typescript-transform-plugin-fc5308fdd943) on how to write a Typescript compiler plugin/transformer.



After applying a first simple transformation which should introduce a type-error (some property accessed on an object that doesn't have that property) I noticed that the no type-error is shown. In fact, the compiler proceeds as normal.



import * as ts from "typescript";

export const transformerFactory = (
program: ts.Program
): ts.TransformerFactory<ts.SourceFile> => {
return (context: ts.TransformationContext): ts.Transformer<ts.SourceFile> => {
const visitor: ts.Visitor = (node: ts.Node): ts.VisitResult<ts.Node> => {
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
if (node.expression.escapedText === "someCall") {
return ts.createCall(
ts.createPropertyAccess(node.expression, "nonExisting"),
node.typeArguments,
node.arguments
);
}
}
return ts.visitEachChild(node, visitor, context);
};

return (sf: ts.SourceFile) => ts.visitNode(sf, visitor);
};
};


Applied to index.ts:



declare function someCall(...args: any): string;

console.log(someCall(1, 2, true));


Yields index.js:



console.log(someCall.nonExisting(1, 2, true));


(even with noEmitOnError: true)



Is this intended behavior? Is this something I can enable somewhere?










share|improve this question































    1















    I'm following a blog (https://dev.doctorevidence.com/how-to-write-a-typescript-transform-plugin-fc5308fdd943) on how to write a Typescript compiler plugin/transformer.



    After applying a first simple transformation which should introduce a type-error (some property accessed on an object that doesn't have that property) I noticed that the no type-error is shown. In fact, the compiler proceeds as normal.



    import * as ts from "typescript";

    export const transformerFactory = (
    program: ts.Program
    ): ts.TransformerFactory<ts.SourceFile> => {
    return (context: ts.TransformationContext): ts.Transformer<ts.SourceFile> => {
    const visitor: ts.Visitor = (node: ts.Node): ts.VisitResult<ts.Node> => {
    if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
    if (node.expression.escapedText === "someCall") {
    return ts.createCall(
    ts.createPropertyAccess(node.expression, "nonExisting"),
    node.typeArguments,
    node.arguments
    );
    }
    }
    return ts.visitEachChild(node, visitor, context);
    };

    return (sf: ts.SourceFile) => ts.visitNode(sf, visitor);
    };
    };


    Applied to index.ts:



    declare function someCall(...args: any): string;

    console.log(someCall(1, 2, true));


    Yields index.js:



    console.log(someCall.nonExisting(1, 2, true));


    (even with noEmitOnError: true)



    Is this intended behavior? Is this something I can enable somewhere?










    share|improve this question



























      1












      1








      1








      I'm following a blog (https://dev.doctorevidence.com/how-to-write-a-typescript-transform-plugin-fc5308fdd943) on how to write a Typescript compiler plugin/transformer.



      After applying a first simple transformation which should introduce a type-error (some property accessed on an object that doesn't have that property) I noticed that the no type-error is shown. In fact, the compiler proceeds as normal.



      import * as ts from "typescript";

      export const transformerFactory = (
      program: ts.Program
      ): ts.TransformerFactory<ts.SourceFile> => {
      return (context: ts.TransformationContext): ts.Transformer<ts.SourceFile> => {
      const visitor: ts.Visitor = (node: ts.Node): ts.VisitResult<ts.Node> => {
      if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
      if (node.expression.escapedText === "someCall") {
      return ts.createCall(
      ts.createPropertyAccess(node.expression, "nonExisting"),
      node.typeArguments,
      node.arguments
      );
      }
      }
      return ts.visitEachChild(node, visitor, context);
      };

      return (sf: ts.SourceFile) => ts.visitNode(sf, visitor);
      };
      };


      Applied to index.ts:



      declare function someCall(...args: any): string;

      console.log(someCall(1, 2, true));


      Yields index.js:



      console.log(someCall.nonExisting(1, 2, true));


      (even with noEmitOnError: true)



      Is this intended behavior? Is this something I can enable somewhere?










      share|improve this question
















      I'm following a blog (https://dev.doctorevidence.com/how-to-write-a-typescript-transform-plugin-fc5308fdd943) on how to write a Typescript compiler plugin/transformer.



      After applying a first simple transformation which should introduce a type-error (some property accessed on an object that doesn't have that property) I noticed that the no type-error is shown. In fact, the compiler proceeds as normal.



      import * as ts from "typescript";

      export const transformerFactory = (
      program: ts.Program
      ): ts.TransformerFactory<ts.SourceFile> => {
      return (context: ts.TransformationContext): ts.Transformer<ts.SourceFile> => {
      const visitor: ts.Visitor = (node: ts.Node): ts.VisitResult<ts.Node> => {
      if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
      if (node.expression.escapedText === "someCall") {
      return ts.createCall(
      ts.createPropertyAccess(node.expression, "nonExisting"),
      node.typeArguments,
      node.arguments
      );
      }
      }
      return ts.visitEachChild(node, visitor, context);
      };

      return (sf: ts.SourceFile) => ts.visitNode(sf, visitor);
      };
      };


      Applied to index.ts:



      declare function someCall(...args: any): string;

      console.log(someCall(1, 2, true));


      Yields index.js:



      console.log(someCall.nonExisting(1, 2, true));


      (even with noEmitOnError: true)



      Is this intended behavior? Is this something I can enable somewhere?







      typescript plugins transformer






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 23 '18 at 14:46







      Werner de Groot

















      asked Nov 23 '18 at 14:39









      Werner de GrootWerner de Groot

      30328




      30328
























          1 Answer
          1






          active

          oldest

          votes


















          2















          Is this intended behavior?




          Yes.




          Is this something I can enable somewhere?




          No, transformers have limited purpose. General all-purpose "plugins" for the compiler are not supported.



          Transformers are run as part of the "emit" phase which generates javascript code from type-checked AST.



          This comment in the transformers PR says




          Transforms, all of them, happen after the checking phase has happened




          UPDATE




          is there some way to compile twice: once to transform the file and once to type-check the whole thing? I don't mind if I have to run a separate check for the transformed files.




          I don't know. The first thing to try is to have your transformers modify AST as before, then type-check modified files manually by calling



          program.getDiagnosticsProducingTypeChecker().getDiagnostics(sourceFile)


          (getDiagnostics has second parameter - cancellationToken - but it seems that it's safe to omit it because it's always checked against being undefined in the type checker code. In general, you can look how various compiler APIs are used in its own source code, for example emit does type-checking first by calling various program.getNNNDiagnostics, then runs emitter with transforms.)



          This might or might not work, because type checker modifies AST, and it depends on AST being in the correct state.



          Then, you might want to look at the builder API - it's purpose is to watch for source file modifications and recompile changed files (source code link). I don't know how hard it would be to make it recompile on AST modifications, also it looks like you would not be able to use visitors available in tranformers; you'll have to traverse AST manually.



          Also, there's ts-simple-ast library, whose stated purpose is to "Provide a simple way to navigate and manipulate TypeScript and JavaScript code". I haven't used it myself and have no idea how useful it is for your goal.






          share|improve this answer


























          • I was afraid of that! Thank you for your answer!

            – Werner de Groot
            Nov 24 '18 at 11:55











          • Do you know a way to achieve more or less the same thing? I see that I can get a ts.Typechecker-instance from ts.Program. Is that something I can use to type-check my new nodes? Or is there some way to compile twice: once to transform the file and once to type-check the whole thing? I don't mind if I have to run a separate check for the transformed files. Any help would be greatly appreciated!

            – Werner de Groot
            Nov 24 '18 at 11:57











          • @WernerdeGroot I updated the answer

            – artem
            Nov 24 '18 at 16:20











          • Thanks! I will definitely try that out! Will also report back if I'm succesful :)

            – Werner de Groot
            Nov 26 '18 at 6:04












          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53448691%2ftypechecking-after-running-typescript-compiler-plugin-transformer%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          2















          Is this intended behavior?




          Yes.




          Is this something I can enable somewhere?




          No, transformers have limited purpose. General all-purpose "plugins" for the compiler are not supported.



          Transformers are run as part of the "emit" phase which generates javascript code from type-checked AST.



          This comment in the transformers PR says




          Transforms, all of them, happen after the checking phase has happened




          UPDATE




          is there some way to compile twice: once to transform the file and once to type-check the whole thing? I don't mind if I have to run a separate check for the transformed files.




          I don't know. The first thing to try is to have your transformers modify AST as before, then type-check modified files manually by calling



          program.getDiagnosticsProducingTypeChecker().getDiagnostics(sourceFile)


          (getDiagnostics has second parameter - cancellationToken - but it seems that it's safe to omit it because it's always checked against being undefined in the type checker code. In general, you can look how various compiler APIs are used in its own source code, for example emit does type-checking first by calling various program.getNNNDiagnostics, then runs emitter with transforms.)



          This might or might not work, because type checker modifies AST, and it depends on AST being in the correct state.



          Then, you might want to look at the builder API - it's purpose is to watch for source file modifications and recompile changed files (source code link). I don't know how hard it would be to make it recompile on AST modifications, also it looks like you would not be able to use visitors available in tranformers; you'll have to traverse AST manually.



          Also, there's ts-simple-ast library, whose stated purpose is to "Provide a simple way to navigate and manipulate TypeScript and JavaScript code". I haven't used it myself and have no idea how useful it is for your goal.






          share|improve this answer


























          • I was afraid of that! Thank you for your answer!

            – Werner de Groot
            Nov 24 '18 at 11:55











          • Do you know a way to achieve more or less the same thing? I see that I can get a ts.Typechecker-instance from ts.Program. Is that something I can use to type-check my new nodes? Or is there some way to compile twice: once to transform the file and once to type-check the whole thing? I don't mind if I have to run a separate check for the transformed files. Any help would be greatly appreciated!

            – Werner de Groot
            Nov 24 '18 at 11:57











          • @WernerdeGroot I updated the answer

            – artem
            Nov 24 '18 at 16:20











          • Thanks! I will definitely try that out! Will also report back if I'm succesful :)

            – Werner de Groot
            Nov 26 '18 at 6:04
















          2















          Is this intended behavior?




          Yes.




          Is this something I can enable somewhere?




          No, transformers have limited purpose. General all-purpose "plugins" for the compiler are not supported.



          Transformers are run as part of the "emit" phase which generates javascript code from type-checked AST.



          This comment in the transformers PR says




          Transforms, all of them, happen after the checking phase has happened




          UPDATE




          is there some way to compile twice: once to transform the file and once to type-check the whole thing? I don't mind if I have to run a separate check for the transformed files.




          I don't know. The first thing to try is to have your transformers modify AST as before, then type-check modified files manually by calling



          program.getDiagnosticsProducingTypeChecker().getDiagnostics(sourceFile)


          (getDiagnostics has second parameter - cancellationToken - but it seems that it's safe to omit it because it's always checked against being undefined in the type checker code. In general, you can look how various compiler APIs are used in its own source code, for example emit does type-checking first by calling various program.getNNNDiagnostics, then runs emitter with transforms.)



          This might or might not work, because type checker modifies AST, and it depends on AST being in the correct state.



          Then, you might want to look at the builder API - it's purpose is to watch for source file modifications and recompile changed files (source code link). I don't know how hard it would be to make it recompile on AST modifications, also it looks like you would not be able to use visitors available in tranformers; you'll have to traverse AST manually.



          Also, there's ts-simple-ast library, whose stated purpose is to "Provide a simple way to navigate and manipulate TypeScript and JavaScript code". I haven't used it myself and have no idea how useful it is for your goal.






          share|improve this answer


























          • I was afraid of that! Thank you for your answer!

            – Werner de Groot
            Nov 24 '18 at 11:55











          • Do you know a way to achieve more or less the same thing? I see that I can get a ts.Typechecker-instance from ts.Program. Is that something I can use to type-check my new nodes? Or is there some way to compile twice: once to transform the file and once to type-check the whole thing? I don't mind if I have to run a separate check for the transformed files. Any help would be greatly appreciated!

            – Werner de Groot
            Nov 24 '18 at 11:57











          • @WernerdeGroot I updated the answer

            – artem
            Nov 24 '18 at 16:20











          • Thanks! I will definitely try that out! Will also report back if I'm succesful :)

            – Werner de Groot
            Nov 26 '18 at 6:04














          2












          2








          2








          Is this intended behavior?




          Yes.




          Is this something I can enable somewhere?




          No, transformers have limited purpose. General all-purpose "plugins" for the compiler are not supported.



          Transformers are run as part of the "emit" phase which generates javascript code from type-checked AST.



          This comment in the transformers PR says




          Transforms, all of them, happen after the checking phase has happened




          UPDATE




          is there some way to compile twice: once to transform the file and once to type-check the whole thing? I don't mind if I have to run a separate check for the transformed files.




          I don't know. The first thing to try is to have your transformers modify AST as before, then type-check modified files manually by calling



          program.getDiagnosticsProducingTypeChecker().getDiagnostics(sourceFile)


          (getDiagnostics has second parameter - cancellationToken - but it seems that it's safe to omit it because it's always checked against being undefined in the type checker code. In general, you can look how various compiler APIs are used in its own source code, for example emit does type-checking first by calling various program.getNNNDiagnostics, then runs emitter with transforms.)



          This might or might not work, because type checker modifies AST, and it depends on AST being in the correct state.



          Then, you might want to look at the builder API - it's purpose is to watch for source file modifications and recompile changed files (source code link). I don't know how hard it would be to make it recompile on AST modifications, also it looks like you would not be able to use visitors available in tranformers; you'll have to traverse AST manually.



          Also, there's ts-simple-ast library, whose stated purpose is to "Provide a simple way to navigate and manipulate TypeScript and JavaScript code". I haven't used it myself and have no idea how useful it is for your goal.






          share|improve this answer
















          Is this intended behavior?




          Yes.




          Is this something I can enable somewhere?




          No, transformers have limited purpose. General all-purpose "plugins" for the compiler are not supported.



          Transformers are run as part of the "emit" phase which generates javascript code from type-checked AST.



          This comment in the transformers PR says




          Transforms, all of them, happen after the checking phase has happened




          UPDATE




          is there some way to compile twice: once to transform the file and once to type-check the whole thing? I don't mind if I have to run a separate check for the transformed files.




          I don't know. The first thing to try is to have your transformers modify AST as before, then type-check modified files manually by calling



          program.getDiagnosticsProducingTypeChecker().getDiagnostics(sourceFile)


          (getDiagnostics has second parameter - cancellationToken - but it seems that it's safe to omit it because it's always checked against being undefined in the type checker code. In general, you can look how various compiler APIs are used in its own source code, for example emit does type-checking first by calling various program.getNNNDiagnostics, then runs emitter with transforms.)



          This might or might not work, because type checker modifies AST, and it depends on AST being in the correct state.



          Then, you might want to look at the builder API - it's purpose is to watch for source file modifications and recompile changed files (source code link). I don't know how hard it would be to make it recompile on AST modifications, also it looks like you would not be able to use visitors available in tranformers; you'll have to traverse AST manually.



          Also, there's ts-simple-ast library, whose stated purpose is to "Provide a simple way to navigate and manipulate TypeScript and JavaScript code". I haven't used it myself and have no idea how useful it is for your goal.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 24 '18 at 16:20

























          answered Nov 23 '18 at 15:38









          artemartem

          15.8k13040




          15.8k13040













          • I was afraid of that! Thank you for your answer!

            – Werner de Groot
            Nov 24 '18 at 11:55











          • Do you know a way to achieve more or less the same thing? I see that I can get a ts.Typechecker-instance from ts.Program. Is that something I can use to type-check my new nodes? Or is there some way to compile twice: once to transform the file and once to type-check the whole thing? I don't mind if I have to run a separate check for the transformed files. Any help would be greatly appreciated!

            – Werner de Groot
            Nov 24 '18 at 11:57











          • @WernerdeGroot I updated the answer

            – artem
            Nov 24 '18 at 16:20











          • Thanks! I will definitely try that out! Will also report back if I'm succesful :)

            – Werner de Groot
            Nov 26 '18 at 6:04



















          • I was afraid of that! Thank you for your answer!

            – Werner de Groot
            Nov 24 '18 at 11:55











          • Do you know a way to achieve more or less the same thing? I see that I can get a ts.Typechecker-instance from ts.Program. Is that something I can use to type-check my new nodes? Or is there some way to compile twice: once to transform the file and once to type-check the whole thing? I don't mind if I have to run a separate check for the transformed files. Any help would be greatly appreciated!

            – Werner de Groot
            Nov 24 '18 at 11:57











          • @WernerdeGroot I updated the answer

            – artem
            Nov 24 '18 at 16:20











          • Thanks! I will definitely try that out! Will also report back if I'm succesful :)

            – Werner de Groot
            Nov 26 '18 at 6:04

















          I was afraid of that! Thank you for your answer!

          – Werner de Groot
          Nov 24 '18 at 11:55





          I was afraid of that! Thank you for your answer!

          – Werner de Groot
          Nov 24 '18 at 11:55













          Do you know a way to achieve more or less the same thing? I see that I can get a ts.Typechecker-instance from ts.Program. Is that something I can use to type-check my new nodes? Or is there some way to compile twice: once to transform the file and once to type-check the whole thing? I don't mind if I have to run a separate check for the transformed files. Any help would be greatly appreciated!

          – Werner de Groot
          Nov 24 '18 at 11:57





          Do you know a way to achieve more or less the same thing? I see that I can get a ts.Typechecker-instance from ts.Program. Is that something I can use to type-check my new nodes? Or is there some way to compile twice: once to transform the file and once to type-check the whole thing? I don't mind if I have to run a separate check for the transformed files. Any help would be greatly appreciated!

          – Werner de Groot
          Nov 24 '18 at 11:57













          @WernerdeGroot I updated the answer

          – artem
          Nov 24 '18 at 16:20





          @WernerdeGroot I updated the answer

          – artem
          Nov 24 '18 at 16:20













          Thanks! I will definitely try that out! Will also report back if I'm succesful :)

          – Werner de Groot
          Nov 26 '18 at 6:04





          Thanks! I will definitely try that out! Will also report back if I'm succesful :)

          – Werner de Groot
          Nov 26 '18 at 6:04




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53448691%2ftypechecking-after-running-typescript-compiler-plugin-transformer%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          這個網誌中的熱門文章

          Xamarin.form Move up view when keyboard appear

          Post-Redirect-Get with Spring WebFlux and Thymeleaf

          Anylogic : not able to use stopDelay()