Typescript 3.7 broke plugin builds

I decided I wanted to take advantage of the latest typescript features, most importantly optional chaining. Has anyone run into issues with a previously working project but no longer compiles with the latest TS. Are there some config changes I need to turn off to let the TS compiler work the old way in some cases?

A brand new cli project will build just fine. I’m just wondering if anyone has run into any issues.

1 Like

well, at least post the error message here? It may or may not be related to Aurelia at all

This actually occurs when building a plugin, not a regular build.

  { uid: 6,
  name: 'processPluginJavaScript',
  branch: false,
  error:
   { Error: TypeScript: Compilation failed
       at Output.mightFinish (D:\Source\aurelia\aurelia-syncfusion-ej2-bridge\node_modules\gulp-typescript\release\output.js:131:43)
       at applySourceMap.then.appliedSourceMap (D:\Source\aurelia\aurelia-syncfusion-ej2-bridge\node_modules\gulp-typescript\release\output.js:66:22)
     domainEmitter:
      CompileStream {
        _readableState: [ReadableState],
        readable: true,
        domain: [Domain],
        _events: [Object],
        _eventsCount: 3,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: true,
        allowHalfOpen: true,
        js: [CompileOutputStream],
        dts: [CompileOutputStream],
        project: [Object] },
     domain:
      Domain {
        domain: null,
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        members: [],
        [Symbol(kWeak)]: WeakReference {} },
     domainThrown: false },
  duration: [ 12, 988290899 ],
  time: 1578426596305 }
{ uid: 2,
  name: '<parallel>',
  branch: true,
  error:
   { Error: TypeScript: Compilation failed
       at Output.mightFinish (D:\Source\aurelia\aurelia-syncfusion-ej2-bridge\node_modules\gulp-typescript\release\output.js:131:43)
       at applySourceMap.then.appliedSourceMap (D:\Source\aurelia\aurelia-syncfusion-ej2-bridge\node_modules\gulp-typescript\release\output.js:66:22)
     domainEmitter:
      CompileStream {
        _readableState: [ReadableState],
        readable: true,
        domain: [Domain],
        _events: [Object],
        _eventsCount: 3,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: true,
        allowHalfOpen: true,
        js: [CompileOutputStream],
        dts: [CompileOutputStream],
        project: [Object] },
     domain:
      Domain {
        domain: null,
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        members: [],
        [Symbol(kWeak)]: WeakReference {} },
     domainThrown: false },
  duration: [ 13, 37538601 ],
  time: 1578426596352 }
{ uid: 0,
  name: '<series>',
  branch: true,
  error:
   { Error: TypeScript: Compilation failed
       at Output.mightFinish (D:\Source\aurelia\aurelia-syncfusion-ej2-bridge\node_modules\gulp-typescript\release\output.js:131:43)
       at applySourceMap.then.appliedSourceMap (D:\Source\aurelia\aurelia-syncfusion-ej2-bridge\node_modules\gulp-typescript\release\output.js:66:22)
     domainEmitter:
      CompileStream {
        _readableState: [ReadableState],
        readable: true,
        domain: [Domain],
        _events: [Object],
        _eventsCount: 3,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: true,
        allowHalfOpen: true,
        js: [CompileOutputStream],
        dts: [CompileOutputStream],
        project: [Object] },
     domain:
      Domain {
        domain: null,
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        members: [],
        [Symbol(kWeak)]: WeakReference {} },
     domainThrown: false },
  duration: [ 13, 201864600 ],
  time: 1578426596459 }
TypeScript: 3 semantic errors
TypeScript: emit succeeded (with errors)
{ uid: 10,
  name: 'processPluginJavaScript',
  branch: false,
  error:
   { Error: TypeScript: Compilation failed
       at Output.mightFinish (D:\Source\aurelia\aurelia-syncfusion-ej2-bridge\node_modules\gulp-typescript\release\output.js:131:43)
       at applySourceMap.then.appliedSourceMap (D:\Source\aurelia\aurelia-syncfusion-ej2-bridge\node_modules\gulp-typescript\release\output.js:66:22)
     domainEmitter:
      CompileStream {
        _readableState: [ReadableState],
        readable: true,
        domain: [Domain],
        _events: [Object],
        _eventsCount: 3,
        _maxListeners: undefined,
        _writableState: [WritableState],
        writable: true,
        allowHalfOpen: true,
        js: [CompileOutputStream],
        dts: [CompileOutputStream],
        project: [Object] },
     domain:
      Domain {
        domain: null,
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        members: [],
        [Symbol(kWeak)]: WeakReference {} },
     domainThrown: false },
  duration: [ 13, 175219300 ],
  time: 1578426596493 }
{ Error: TypeScript: Compilation failed
    at Output.mightFinish (D:\Source\aurelia\aurelia-syncfusion-ej2-bridge\node_modules\gulp-typescript\release\output.js:131:43)
    at applySourceMap.then.appliedSourceMap (D:\Source\aurelia\aurelia-syncfusion-ej2-bridge\node_modules\gulp-typescript\release\output.js:66:22)
  domainEmitter:
   CompileStream {
     _readableState:
      ReadableState {
        objectMode: true,
        highWaterMark: 16,
        buffer: BufferList { head: null, tail: null, length: 0 },
        length: 0,
        pipes: [Pumpify],
        pipesCount: 1,
        flowing: true,
        ended: true,
        endEmitted: false,
        reading: false,
        sync: false,
        needReadable: false,
        emittedReadable: false,
        readableListening: false,
        resumeScheduled: false,
        paused: false,
        emitClose: true,
        autoDestroy: false,
        destroyed: false,
        defaultEncoding: 'utf8',
        awaitDrain: 0,
        readingMore: true,
        decoder: null,
        encoding: null },
     readable: true,
     domain:
      Domain {
        domain: null,
        _events: [Object],
        _eventsCount: 2,
        _maxListeners: undefined,
        members: [],
        [Symbol(kWeak)]: WeakReference {} },
     _events:
      [Object: null prototype] { finish: [Function], end: [Function], data: [Function: ondata] },
     _eventsCount: 3,
     _maxListeners: undefined,
     _writableState:
      WritableState {
        objectMode: true,
        highWaterMark: 16,
        finalCalled: false,
        needDrain: false,
        ending: false,
        ended: false,
        finished: false,
        destroyed: false,
        decodeStrings: true,
        defaultEncoding: 'utf8',
        length: 0,
        writing: false,
        corked: 0,
        sync: false,
        bufferProcessing: false,
        onwrite: [Function: bound onwrite],
        writecb: null,
        writelen: 0,
        bufferedRequest: null,
        lastBufferedRequest: null,
        pendingcb: 0,
        prefinished: false,
        errorEmitted: false,
        emitClose: true,
        autoDestroy: false,
        bufferedRequestCount: 0,
        corkedRequestsFree: [Object] },
     writable: true,
     allowHalfOpen: true,
     js:
      CompileOutputStream {
        _readableState: [ReadableState],
        readable: true,
        domain: [Domain],
        _events: [Object: null prototype] {},
        _eventsCount: 0,
        _maxListeners: undefined },
     dts:
      CompileOutputStream {
        _readableState: [ReadableState],
        readable: true,
        domain: [Domain],
        _events: [Object: null prototype] {},
        _eventsCount: 0,
        _maxListeners: undefined },
     project:
      { input: [FileCache],
        singleOutput: false,
        compiler: [ProjectCompiler],
        options: [Object],
        projectReferences: undefined,
        typescript: [Object],
        directory: 'D:\\Source\\aurelia\\aurelia-syncfusion-ej2-bridge',
        output: [Output],
        reporter: [Object] } },
  domain:
   Domain {
     domain: null,
     _events:
      [Object: null prototype] {
        removeListener: [Function: updateExceptionCapture],
        newListener: [Function: updateExceptionCapture] },
     _eventsCount: 2,
     _maxListeners: undefined,
     members: [],
     [Symbol(kWeak)]: WeakReference {} },
  domainThrown: false }
1 Like

Quickly looking at the error I would try to turn off source map creation and see if it works without.

1 Like

Good thought but that didn’t solve it

1 Like

Hmm shame, I will check if I already updated my extension repo. I am actively using 3.7 where I can, I think I also upgraded my component library but will double check and let you know

2 Likes

I use TS 3.7 with Optional Chaining, but for that I had to modify the tsconfig.json Target to es2020 prior to this I had it set to esnext but I read somewhere that it doesn’t work with next (it might in the future) and so try changing it "target": "es2020", and that is under the compilerOptions. I think you can also target something lower, just don’t use next as it won’t work.

So in my case, I got it working in both the backend (with NestJS) and frontend (Aurelia)

EDIT
Here’s where I found it, it’s from this SO answer that got me going. There’s also a comment which says that you if you do this change then you lose BigInt because it’s not in es2020 yet but I’m not using that so that is fine by me… oh and your Editor has to support it as well, for the intellisense I think, VSCode always use latest TS so it’s good but it might not work with other Editors.

Hmm actually that is probably not your problem since after re-reading your post, you mention it’s only for plugin build.

2 Likes

You should check release notes for breaking changes in typescript.

TypeScript team doesn’t follow semver (major version bump for breaking changes). Their argument is that if they bump major version for every release of breaking changes, there will be only major versions because there are always breaking changes due to the complexity of the project.

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#37-breaking-changes

1 Like

I’m on ts 3.7.2 for the component library i’m working on which is an aurelia plugin and it’s working just fine. My compiler target is “es5”.

2 Likes

Sigh, well it looks like clearing my node_modules fixed things. Thank you to all that chimed in. I despise NPM

1 Like

Also just so that all of you know, it is not recommended to use TypeScript 3.7.x in a plugin/lib because the TypeScript team merged this breaking change. I found this bug while using NestJS (nodeJS framework) and they had to downgrade the framework to TS 3.6.x because I opened a regression bug in that framework and from what I understand the TS team doesn’t want to budge… the end story of this is that if the plugin/lib uses TS 3.7.x to build their plugin/lib, then it requires every user of their plugin/lib to use TS 3.7 or else it breaks for those users and a framework like NestJS cannot afford to do that and so they had to revert to an older TS version 3.6.x (which kinda sux).

It’s most probably not really related to your issue, but it’s totally worth to know about.

BTW, the bug (or regression) in question is that it changes the signature of the compiled d.ts file, it adds a get in front of every getter while it wasn’t doing that in previous version. For example, prior to 3.7the d.ts would have

axiosRef(): AxiosInstance

with 3.7 and up it’s now (notice the get in the front)

get axiosRef(): AxiosInstance

then if you have a TS version lower than 3.7 (like 3.6), you will get this new breaking error

node_modules/@nestjs/common/http/http.service.d.ts:13:9 - 
error TS1086: An accessor cannot be declared in an ambient context.
13     get axiosRef(): AxiosInstance;
           ~~~~~~~~
2 Likes

That is great info and should be well documented on the plugin page. For me it’s not an issue thankfully as my plugins are all private

1 Like

2 of my plugin projects are good, the 3rd, which relies on Syncfusion javascript controls has this issue. I’m not sure if this is what is breaking the build, I can’t just remove it as the plugin’s purpose is to wrap them.

As long as I keep that one project using some older TS, i should be okay. My consuming project is okay at 3.7.4

1 Like

How can I target older TS version in only one project??

1 Like

I’m not sure if you understand what I wrote about the “not recommended” to use TS 3.7 for plugin/lib. It’s mostly to still be compatible for users who have not upgraded to latest TS, but if you are using TS 3.7 then you shouldn’t have that problem, as long as you don’t target esnext which doesn’t work for Optional Chaining. I think there can only be 1 target per project since it uses 1 tsconfig file.

What is the error that you’re getting anyway?

1 Like

I understood exactly what you meant. My issue isn’t the same as what you ran into, but one of my imported libraries has an issue with 3.7.x so I need to drop down to the previous version.

2 Likes

Syncfusion said they’ll have a fix coming out next week for this issue.

2 Likes

I’m not sure if you use Syncfusion for the grid, but if it’s for the grid, you should take a look at my lib Aurelia-Slickgrid it’s so much better and there’s no issue with TS 3.7 :wink:

2 Likes

I’m too far along to just switch.

I’ve eliminated all jQuery code from my project. Not a great reason to not use it, so it really comes down I don’t have time to switch grids

1 Like

Not sure if you’re aware but the target compiler option tells Typescript what level of JavaScript to transpile to. If you target es2020 and use optional chaining, your output code will still contain optional chaining and will not work in Firefox or Safari unless you are transpiling again after Optional chaining (?.) - JavaScript | MDN

2 Likes