Utilizing the Typescript Compiler API type checker, I am analyzing identifier nodes in a loaded file to determine their types within a program.
To begin, I load the file and initialize the program and type checker like so:
const program = ts.createProgram([document.uri.fsPath], { allowJs: true, strict: true });
const checker = program.getTypeChecker();
const sourceFile = program.getSourceFile(document.uri.fsPath);
Next, I traverse the Abstract Syntax Tree (AST) using ts.forEachChild
. Upon finding a node of interest, I use the type checker to retrieve its type as follows:
const type = checker.getTypeAtLocation(node);
const typeAsString = checker.typeToString(type, node, typeFormatFlag);
Consider this sample file:
//spreadArray.tsx
import React from 'react';
interface ComponentProps {
items: string[];
}
function Component(props: ComponentProps) {
const {
items: [item1, item2, ...otherItems]
} = props;
return (
<div className='my-class-2'>
<div>{item1}</div>
<div>{item2}</div>
<div>{otherItems.join(', ')}</div>
</div>
);
}
I want to know the types of item1
, item2
, and otherItems
. While hovering over these variables in the original file provides correct types (string, string, string[]), running my program results in incorrect resolutions (any, any, {}). This inconsistency extends to various other types such as arrow functions, promises, and objects.
Running integration tests with files like the above sometimes yields correct types but also exhibits wrong resolutions at times. The codebase and test environment share the same TypeScript version and tsconfig settings.
The project configurations are as follows:
tsconfig.json
{
"compilerOptions": {
"jsx": "react",
"module": "Node16",
"target": "ES2022",
"lib": ["ES2022"],
"sourceMap": true,
"rootDir": "src",
"strict": true
}
}
package.json
//....
"devDependencies": {
"@types/mocha": "^10.0.6",
"@types/node": "18.x",
"@types/react": "^18.2.58",
"@types/react-dom": "^18.2.19",
"@types/vscode": "^1.86.0",
"@typescript-eslint/eslint-plugin": "^6.19.1",
"@typescript-eslint/parser": "^6.19.1",
"@vscode/test-cli": "^0.0.4",
"@vscode/test-electron": "^2.3.9",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"prettier": "^3.2.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"ts-loader": "^9.5.1",
"webpack": "^5.90.0",
"webpack-cli": "^5.1.4"
},
"dependencies": {
"typescript": "^5.3.3"
}
Node version: 18.17.1
In attempting to rectify the issue, I've experimented with alternative methods like getSymbolAtLocation(node)
and
getTypeOfSymbolAtLocation(symbol, node)
without success. Various versions of TypeScript 5.x and testing across React and TypeScript projects have resulted in inaccurate type resolutions.
This consistently erroneous resolution, often defaulting to any or unknown and empty objects for arrays, persists across multiple codebases. Notably, more complex expected types tend to exhibit higher chances of incorrect resolution.
I seek insights on what may be causing these discrepancies to improve precision in type determinations, aligning them more closely with IDE variable inspections.