When dealing with SimpleType instances, isAssignableToType doesn't consider string[] assignable to Iterable<string>, although TypeScript considers it assignable. This is the root cause of this lit-analyzer issue.
To replicate the issue:
- Create a project with the following files
npm i
npm run build
node check.js
This (fairly quick-and-dirty) program reads the example.ts file, finds two variable declarations, and checks their assignability with both a TypeScript TypeChecker and (after converting to SimpleType instances) ts-simple-type's isAssignableToType. In the given files, the types are Iterable<string> and string[]. The TypeScript check correctly shows
TypeScript checker results:
Iterable<string> is assignable to string[]? false
string[] is assignable to Iterable<string>? true
but the ts-simple-type isAssignableToType check shows:
ts-simple-type results:
Iterable<string, any, any> is assignable to string[]? false
string[] is assignable to Iterable<string, any, any>? false
Here are the files:
package.json:
{
"name": "typecheck",
"version": "1.0.0",
"main": "check.js",
"scripts": {
"build": "tsc"
},
"dependencies": {
"ts-simple-type": "^1.0.7",
"typescript": "^5.7.3"
},
"devDependencies": {
"@types/node": "^22.10.7"
}
}
tsconfig.json:
{
"compilerOptions": {
"strict": true,
"lib": ["ESNext", "DOM"],
"sourceMap": true
},
"include": ["check.ts"]
}
check.ts:
import * as ts from "typescript";
import { toSimpleType, isAssignableToType, typeToString } from "ts-simple-type";
const program = ts.createProgram({
rootNames: ["example.ts"],
options: { strict: true },
});
const checker = program.getTypeChecker();
const sourceFile = program.getSourceFile("example.ts");
if (sourceFile) {
let nodeA: ts.Node | null = null;
let nodeB: ts.Node | null = null;
const predicate = (node: ts.Node) => {
const flag = ts.isVariableDeclaration(node);
if (flag) {
if (!nodeA) {
nodeA = node;
} else {
nodeB = node;
return true;
}
}
ts.forEachChild(node, predicate);
};
sourceFile.forEachChild(predicate);
if (!nodeA || !nodeB) {
console.log(
`Coudn't find two variable declarations (${nodeA ? 1 : 0} found)`
);
} else {
console.log(`TypeScript checker results:`);
const tsTypeA = checker.getTypeAtLocation(nodeA);
const tsStringA = checker.typeToString(tsTypeA);
const tsTypeB = checker.getTypeAtLocation(nodeB);
const tsStringB = checker.typeToString(tsTypeB);
const tsAssignableAtoB = checker.isTypeAssignableTo(tsTypeA, tsTypeB);
const tsAssignableBtoA = checker.isTypeAssignableTo(tsTypeB, tsTypeA);
console.log(
`${tsStringA} is assignable to ${tsStringB}? ${tsAssignableAtoB}`
);
console.log(
`${tsStringB} is assignable to ${tsStringA}? ${tsAssignableBtoA}`
);
console.log();
console.log(`ts-simple-type results:`);
const simpleTypeA = toSimpleType(tsTypeA, checker);
const simpleStringA = typeToString(simpleTypeA);
const simpleTypeB = toSimpleType(tsTypeB, checker);
const simpleStringB = typeToString(simpleTypeB);
const simpleAssignableAtoB = isAssignableToType(
simpleTypeA,
simpleTypeB
);
const simpleAssignableBtoA = isAssignableToType(
simpleTypeA,
simpleTypeB
);
console.log(
`${simpleStringA} is assignable to ${simpleStringB}? ${simpleAssignableAtoB}`
);
console.log(
`${simpleStringB} is assignable to ${simpleStringA}? ${simpleAssignableBtoA}`
);
}
}
example.ts:
let a: Iterable<string> = [];
let b: string[] = [];
For debugging in VS Code if desired: launch.json:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Node Debug",
"skipFiles": ["<node_internals>/**"],
"program": "check.js"
}
]
}
I've stepped through the code but haven't had the time to really get to grips with the code and why the check fails.
When dealing with
SimpleTypeinstances,isAssignableToTypedoesn't considerstring[]assignable toIterable<string>, although TypeScript considers it assignable. This is the root cause of thislit-analyzerissue.To replicate the issue:
npm inpm run buildnode check.jsThis (fairly quick-and-dirty) program reads the
example.tsfile, finds two variable declarations, and checks their assignability with both a TypeScriptTypeCheckerand (after converting toSimpleTypeinstances)ts-simple-type'sisAssignableToType. In the given files, the types areIterable<string>andstring[]. The TypeScript check correctly showsbut the
ts-simple-typeisAssignableToTypecheck shows:Here are the files:
package.json:{ "name": "typecheck", "version": "1.0.0", "main": "check.js", "scripts": { "build": "tsc" }, "dependencies": { "ts-simple-type": "^1.0.7", "typescript": "^5.7.3" }, "devDependencies": { "@types/node": "^22.10.7" } }tsconfig.json:{ "compilerOptions": { "strict": true, "lib": ["ESNext", "DOM"], "sourceMap": true }, "include": ["check.ts"] }check.ts:example.ts:For debugging in VS Code if desired:
launch.json:{ "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Node Debug", "skipFiles": ["<node_internals>/**"], "program": "check.js" } ] }I've stepped through the code but haven't had the time to really get to grips with the code and why the check fails.