You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Use of the satisfies keyword removes require statements when TS compiler invoked programmatically #51642
Use of the satisfies keyword changes the output of the compiler. Vitally important require statements are missing. Does not appear to happen when using tsc but only when invoking the compiler programmatically as is done by ts-loader from the WebPack project.
🔎 Search Terms
satisfies, webpack, ts-loader, 4.9
🕗 Version & Regression Information
This bug only occurs when using the satisfies keyword.
Note: This is fully demonstrated in the above GitHub repo.
import{z}from"zod";import{isValid}from"./lib";interfaceMyObject{name: string;}exportconstMyObjectSchema=z.object({name: z.string().refine(isValid),})satisfiesz.ZodSchema<MyObject>;// Removing the `satisfies` keyword will change the output of the compilerconsole.log(MyObjectSchema.parse({name: 'foo'}));
"use strict";Object.defineProperty(exports,"__esModule",{value: true});exports.MyObjectSchema=void0;constzod_1=require("zod");// THIS IS MISSING FROM ABOVEconstlib_1=require("./lib");// THIS IS MISSING FROM ABOVEexports.MyObjectSchema=zod_1.z.object({name: zod_1.z.string().refine(lib_1.isValid),});console.log(exports.MyObjectSchema.parse({name: 'foo'}));
🙁 Actual behavior
As with above, using the satisfies keyword results in missing require statements.
🙂 Expected behavior
I expect the use of the satisfies keyword to have no effect on the compiler's outputted JavaScript.
This happens subtly when the asserted type itself is invalid (I'm guessing there's a constraint violation or just missing type in this example); we bail out of checkSatisfiesExpression before checking the asserted expression (which in turn marks the expressions as used). But since transpileModule doesn't resolve references, these imported types are unsubtly always invalid. The fix is straightforward, I'll put up a PR shortly.
However I'm not sure why you say the asserted type is invalid. In my example the code does not have any compiler errors and the satisfies keyword is working as expected (at least as far as displayed compiler messages go). It was just the JS output that was bad. Is this something to do with the way compiler is being invoked? As I say this issue does not manifest when using tsc. It was identified by the way WebPack invokes the compiler, specifically the ts-loader.
As I say this issue does not manifest when using tsc. It was identified by the way WebPack invokes the compiler, specifically the ts-loader.
Yep, hence this part:
But since transpileModule [a TypeScript compiler API for use by third-party tools] doesn't resolve references, these imported types are unsubtly always invalid.
When the compiler is invoked that way, my understanding is that it doesn't disable type checking, but it does disable resolving references and any type errors that result are simply suppressed.
Bruce Pascoe (@fatcerberus) Thanks for taking the time to explain it to me. I guess the compiler couldn't resolve references even if it wanted to because it is being invoked with an out-of-context string of source code. What an interesting edge case.
Just mentioning this also occurs in with ts-node when using --transpile-only aka without type information
I cherry-picked the fix in the PR and can confirm it fixes the problem for me
Yeah, I'm pretty sure using TS in transpile mode doesn't actually disable type checking, it just suppresses all the type errors. It's kind of like setting noEmitOnError: false in your tsconfig and then just ignoring the errors.
Activity
RyanCavanaugh commentedon Nov 30, 2022
This happens subtly when the asserted type itself is invalid (I'm guessing there's a constraint violation or just missing type in this example); we bail out of
checkSatisfiesExpressionbefore checking the asserted expression (which in turn marks the expressions as used). But sincetranspileModuledoesn't resolve references, these imported types are unsubtly always invalid. The fix is straightforward, I'll put up a PR shortly.cjdell commentedon Nov 30, 2022
Ryan Cavanaugh (@RyanCavanaugh) Thanks for sorting this so quickly and I'm glad it was an easy fix.
However I'm not sure why you say the asserted type is invalid. In my example the code does not have any compiler errors and the
satisfieskeyword is working as expected (at least as far as displayed compiler messages go). It was just the JS output that was bad. Is this something to do with the way compiler is being invoked? As I say this issue does not manifest when usingtsc. It was identified by the way WebPack invokes the compiler, specifically thets-loader.fatcerberus commentedon Dec 1, 2022
Yep, hence this part:
When the compiler is invoked that way, my understanding is that it doesn't disable type checking, but it does disable resolving references and any type errors that result are simply suppressed.
cjdell commentedon Dec 1, 2022
Bruce Pascoe (@fatcerberus) Thanks for taking the time to explain it to me. I guess the compiler couldn't resolve references even if it wanted to because it is being invoked with an out-of-context string of source code. What an interesting edge case.
Cellule commentedon Dec 1, 2022
Just mentioning this also occurs in with ts-node when using
--transpile-onlyaka without type informationI cherry-picked the fix in the PR and can confirm it fixes the problem for me
fatcerberus commentedon Dec 1, 2022
Yeah, I'm pretty sure using TS in transpile mode doesn't actually disable type checking, it just suppresses all the type errors. It's kind of like setting
noEmitOnError: falsein your tsconfig and then just ignoring the errors.