Search code examples
typescripttypescript-compiler-api

How can I use the TS compiler API to see if types in a .d.ts have changed?


I'd like to be able to tell if the types in a TypeScript declaration file have changed since the last compilation. Some false positives are OK (saying the types have changed when they haven't) but it's not OK to say that nothing has changed when something has.

For a .d.ts with no imports, I could do a string comparison between the old .dts and the new .d.ts.

But when a .d.ts has imports, its meaning can depend on what is in other files:

import { OtherType } from "./other"
export type Wrapped = { other: OtherType }

In that case, I could recurse through and serialize Wrapped, then compare the serialized representations. But things get pretty complicated with recursive types.

For nominal types, I think I'd have to correlate NodeIds or something.

Is there something in the TS compiler API that does this already or an alternative approach to solving the problem?


Solution

  • I believe the most performant way to do it would be to only work with the ASTs. So instead of a text based diff you could do a "semantic diff" where you parse ASTs using ts.createSourceFile, traverse the nodes using ts.forEachChild creating your own symbol table-like structure of both the old and new declaration files, then compare the structures for differences. Depending on the extent of the implementation, it might lead to some false positives and you'd have to make it understand how to follow import and export declaration module specifiers to the other files.

    An alternate approach would be to use the type checker and get the symbol of both source files (const fileSymbol = typeChecker.getSymbolAtLocation(sourceFile);). From there, you could compare the keys in the exports property then navigate down through the values to the declarations (ex. see this answer).

    Anyway, this is a pretty high level answer. Let me know if you would like me to go into more detail on anything. What you're doing is a tool waiting to be created (ex. checking a declaration file for breaking changes).