Typechecking after running Typescript compiler plugin/transformer
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
add a comment |
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
add a comment |
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
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
typescript plugins transformer
edited Nov 23 '18 at 14:46
asked Nov 23 '18 at 14:39
Werner de Groot
30128
30128
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
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.
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 ats.Typechecker
-instance fromts.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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
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 ats.Typechecker
-instance fromts.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
add a comment |
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.
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 ats.Typechecker
-instance fromts.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
add a comment |
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.
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.
edited Nov 24 '18 at 16:20
answered Nov 23 '18 at 15:38
artem
13.8k12738
13.8k12738
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 ats.Typechecker
-instance fromts.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
add a comment |
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 ats.Typechecker
-instance fromts.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
add a comment |
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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