Skip to content

TypeScript 2.9 Watch API change breaking watch support in ts-loader? #24625

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
johnnyreilly opened this issue Jun 2, 2018 · 6 comments
Closed
Assignees
Labels
API Relates to the public API for TypeScript Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@johnnyreilly
Copy link

Hey everybody! (and in particular @sheetalkamat and @Andy-MS !)

TypeScript Version: 2.9.1

Apologies for raising a bug. I suspect this probably isn't a bug. (Although I suppose it may be.) I'm raising this issue because it may be a bug; but either way I could really benefit from some guidance.

I'm one of the maintainers of ts-loader. I was just doing the relevant housekeeping to cut a new release. I thought I'd switch to building ts-loader with TypeScript 2.9. However, this presents the following compile error:

src/servicesHost.ts:190:9 - error TS2322: Type '{ rootFiles: string[]; options: CompilerOptions; useCaseSensitiveFileNames: () => boolean; getNew...' is not assignable to type 'WatchHost'.
  Types of property 'createProgram' are incompatible.
    Type '{ (newProgram: Program, host: BuilderProgramHost, oldProgram?: BuilderProgram | undefined, config...' is not assignable to type 'CreateProgram<BuilderProgram>'.
      Types of parameters 'newProgram' and 'rootNames' are incompatible.
        Type 'ReadonlyArray<string> | undefined' is not assignable to type 'Program'.
          Type 'undefined' is not assignable to type 'Program'.

190   const watchHost: WatchHost = {
            ~~~~~~~~~

The error message isn't as revealing as it might be but I think it's related to createAbstractBuilder somehow no longer aligning with createProgram.

The easiest way to see this in action is to take the ts-loader source code and amend this line from:

    createProgram: compiler.createAbstractBuilder as any // TODO: Chase up with TypeScript team about API change

to:

    createProgram: compiler.createAbstractBuilder

et voila! Compile error.

I've tried digging through the history of builder.ts and I've a hunch that this may be linked to the strictNullChecks switch that recently happened. Unfortunately I'm not getting enough information from the compiler to meaningful progress this. I'm drawing a blank.

Would you be able to give me some guidance please? My apologies if I'm missing something super obvious.

@johnnyreilly johnnyreilly changed the title TypeScript 2.9 Watch API change breaking Watch support in ts-loader? TypeScript 2.9 Watch API change breaking watch support in ts-loader? Jun 2, 2018
@mhegazy mhegazy added the Bug A bug in TypeScript label Jun 2, 2018
@mhegazy mhegazy added this to the TypeScript 2.9.2 milestone Jun 2, 2018
@felixrabe
Copy link

I also have code that might break because of this ... bug / misunderstanding, that I based on the pull request for https://github.com/Microsoft/TypeScript-wiki/blob/master/Using-the-Compiler-API.md#writing-an-incremental-program-watcher:

import chokidar from 'chokidar'
import fs from 'fs-extra'
import path from 'path'
import { BrowserWindow } from 'electron'
import ts from 'typescript'

import pkgDir from 'pkg-dir'

const ROOT = pkgDir.sync(__dirname)
if (!ROOT) {
  throw new Error(`Could not find a valid project root.`)
}

const ROOT_BUILD_GUI = path.resolve(ROOT, 'build', 'gui')
const ROOT_GUI = path.resolve(ROOT, 'gui')

// based on: https://github.com/Microsoft/TypeScript-wiki/pull/169/
const watchGuiTS = async (): Promise<void> => {
  let resolve: () => void
  const promise = new Promise<void>((res) => { resolve = res })

  const formatHost: ts.FormatDiagnosticsHost = {
    getCanonicalFileName: p => p,
    getCurrentDirectory: ts.sys.getCurrentDirectory,
    getNewLine: () => ts.sys.newLine
  }

  const formatDiagnostic = (diag: ts.Diagnostic) => {
    return ts.formatDiagnostic(diag, formatHost).trimRight()
  }

  // @ts-ignore
  const ignoreDiagnostic = (diag: ts.Diagnostic) => {
    // return [6031, 6032, 6042].indexOf(diag.code) !== -1
    return false
  }

  const reportDiagnostic = (diag: ts.Diagnostic) => {
    if (!ignoreDiagnostic(diag)) {
      console.error(formatDiagnostic(diag))
    }
  }

  let firstTS6042 = true

  const reportWatchStatusChanged = (diag: ts.Diagnostic) => {
    if (firstTS6042 && diag.code === 6042) {
      resolve()
      firstTS6042 = false
    }
    if (!ignoreDiagnostic(diag)) {
      console.info(formatDiagnostic(diag))
    }
  }

  const searchPath = ROOT_GUI

  const configPath = ts.findConfigFile(searchPath, ts.sys.fileExists, 'tsconfig.json')
  if (!configPath) {
    throw new Error(`Could not find a valid 'tsconfig.json'.`)
  }

  const host = ts.createWatchCompilerHost(configPath, {}, ts.sys,
    undefined,
    reportDiagnostic,
    reportWatchStatusChanged,
  )

  ts.createWatchProgram(host)

  return promise
}

// ...

(I've used to use ts.createEmitAndSemanticDiagnosticsBuilderProgram instead of undefined in the call to createWatchCompilerHost and had to change that after upgrading to TS 2.9 (seems to be used by default anyway).)

Calling watchGuiTS now results in these two TS-related messages, and as there is no TS6042 message anymore, the function does not get resolved:

message TS6031: Starting compilation in watch mode...
message TS6194: Found 0 errors. Watching for file changes.

So this is where I'm stuck getting TS 2.9(.1) to work with my project ATM.

@felixrabe
Copy link

felixrabe commented Jun 3, 2018

It might be that my issue (apart from the undefined thing that might be connected to this bug) is unrelated: I just saw that https://github.com/Microsoft/TypeScript/blob/master/src/compiler/diagnosticMessages.json is now missing TS6042 (it was present in the 2.8.3 version), and TS6194 with 0 errors might be the appropriate replacement. (Just guessing, not going on a code dig now.)

@felixrabe
Copy link

Ok, I ended up changing my code around reportWatchStatusChanged to the following:

  const formatDiagnostic = (diag: ts.Diagnostic) => {
    return ts.formatDiagnostic(diag, formatHost).trimRight()
  }

  const ignoreDiagnostic = (diag: ts.Diagnostic) => {
    return [6031, 6032].indexOf(diag.code) !== -1
  }

  const reportDiagnostic = (diag: ts.Diagnostic) => {
    if (!ignoreDiagnostic(diag)) {
      console.error(formatDiagnostic(diag))
    }
  }

  let firstCompilationDone = false

  const isCompilationDone = (diag: ts.Diagnostic) => {
    return diag.code === 6194 && diag.messageText === 'Found 0 errors. Watching for file changes.'
  }

  const reportWatchStatusChanged = (diag: ts.Diagnostic) => {
    if (!firstCompilationDone && isCompilationDone(diag)) {
      resolve()
      firstCompilationDone = true
    }
    if (!ignoreDiagnostic(diag)) {
      console.info(formatDiagnostic(diag))
    }
  }

The part diag.code === 6194 && diag.messageText === 'Found 0 errors. Watching for file changes.' smells like "there is a better way to do this" but it works for now.

@sheetalkamat
Copy link
Member

@felixrabe you want to look for diagnostics code: 6193 and 6194 since those are the replacement for Watching for file changes message.

sheetalkamat added a commit that referenced this issue Jun 4, 2018
…tAndSemanticDiagnosticsBuilderProgram and createAbstractBuilder not assignable to CreateProgram<T>

Fixes #24625
sheetalkamat added a commit that referenced this issue Jun 4, 2018
…tAndSemanticDiagnosticsBuilderProgram and createAbstractBuilder not assignable to CreateProgram<T>

Fixes #24625
@mhegazy mhegazy added Fixed A PR has been merged for this issue API Relates to the public API for TypeScript labels Jun 4, 2018
@johnnyreilly
Copy link
Author

Well done! 🌻

@mhegazy
Copy link
Contributor

mhegazy commented Jun 4, 2018

fix should be in typescript@next later tonight, and in typescript@2.9.2 in a week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API Relates to the public API for TypeScript Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

4 participants