Skip to content

Commit 2cd9a46

Browse files
Bump @ts-morph/bootstrap from 0.22.0 to 0.29.0 (#28)
* Bump @ts-morph/bootstrap from 0.22.0 to 0.29.0 Bumps [@ts-morph/bootstrap](https://github.com/dsherret/ts-morph) from 0.22.0 to 0.29.0. - [Release notes](https://github.com/dsherret/ts-morph/releases) - [Commits](dsherret/ts-morph@tsa-0.22.0...tsa-0.29.0) --- updated-dependencies: - dependency-name: "@ts-morph/bootstrap" dependency-version: 0.29.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * update eslint and other tools for new versions * use node globals * lint * support symbol transpilation --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Lars Melchior <lars.melchior@gmail.com>
1 parent a833e01 commit 2cd9a46

20 files changed

Lines changed: 546 additions & 584 deletions

.eslintrc.js

Lines changed: 0 additions & 25 deletions
This file was deleted.

eslint.config.mts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import js from "@eslint/js";
2+
import globals from "globals";
3+
import tseslint from "typescript-eslint";
4+
import { defineConfig } from "eslint/config";
5+
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
6+
7+
export default defineConfig([
8+
{ files: ["**/*.{js,mjs,cjs,ts,mts,cts}"], plugins: { js }, extends: ["js/recommended"], languageOptions: { globals: globals.node } },
9+
tseslint.configs.recommendedTypeChecked,
10+
{
11+
languageOptions: {
12+
parserOptions: {
13+
projectService: true,
14+
},
15+
},
16+
},
17+
eslintPluginPrettierRecommended,
18+
]);

package.json

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,30 +20,34 @@
2020
"dependencies": {
2121
"@commander-js/extra-typings": "^12.1.0",
2222
"commander": "^12.1.0",
23-
"typescript": "^5.3.3"
23+
"typescript": "^6.0.3"
2424
},
2525
"devDependencies": {
2626
"@babel/cli": "^7.28.6",
2727
"@babel/core": "^7.29.0",
2828
"@babel/node": "^7.22.19",
2929
"@babel/preset-env": "^7.23.7",
3030
"@babel/preset-typescript": "^7.28.5",
31-
"@ts-morph/bootstrap": "^0.22.0",
31+
"@eslint/js": "^10.0.1",
32+
"@ts-morph/bootstrap": "^0.29.0",
3233
"@types/jest": "^29.5.11",
33-
"@types/node": "^20.10.6",
34-
"@typescript-eslint/eslint-plugin": "^6.17.0",
35-
"@typescript-eslint/parser": "^6.21.0",
36-
"eslint": "^8.56.0",
37-
"eslint-config-prettier": "^9.1.0",
34+
"@types/node": "^25.6.0",
35+
"@typescript-eslint/eslint-plugin": "^8.59.0",
36+
"@typescript-eslint/parser": "^8.59.0",
37+
"eslint": "^10.2.1",
38+
"eslint-config-prettier": "^10.1.8",
3839
"eslint-plugin-prettier": "^5.1.2",
40+
"globals": "^17.5.0",
3941
"jest": "^29.7.0",
40-
"prettier": "^3.1.1"
42+
"jiti": "^2.6.1",
43+
"prettier": "^3.1.1",
44+
"typescript-eslint": "^8.59.0"
4145
},
4246
"scripts": {
4347
"watch": "babel-node --watch -x .ts --",
4448
"single": "babel-node -x .ts",
4549
"develop": "yarn watch src/index.ts",
46-
"lint": "eslint src/**/*.ts",
50+
"lint": "eslint src",
4751
"build": "babel --extensions .ts --ignore '**/*.test.ts' ./src -d dist --source-maps",
4852
"test": "jest",
4953
"typecheck": "tsc -p . --noEmit",

src/ParserState.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ export type ParserState = {
1111
config: Ts2PyConfig;
1212
};
1313

14-
export const createNewParserState = (typechecker: ts.TypeChecker, config: Ts2PyConfig): ParserState => {
14+
export const createNewParserState = (
15+
typechecker: ts.TypeChecker,
16+
config: Ts2PyConfig,
17+
): ParserState => {
1518
const knownTypes = new Map<ts.Type, string>();
1619
knownTypes.set(typechecker.getVoidType(), "None");
1720
knownTypes.set(typechecker.getNullType(), "None");
@@ -29,4 +32,4 @@ export const createNewParserState = (typechecker: ts.TypeChecker, config: Ts2PyC
2932
canonicalTypeNames: new Map(),
3033
config,
3134
};
32-
}
35+
};

src/canonicalTypeName.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,21 @@ import { createNewParserState, ParserState } from "./ParserState";
22
import ts from "typescript";
33
import { parseTypeDefinition } from "./parseTypeDefinition";
44

5-
/**
5+
/**
66
* A function that creates a unique string for a given interface or object type,
77
* from a fresh parser state. This should return the same string for two semantically
88
* identically types, allowing us to re-use existing helper types if the generated
9-
* strings match.
9+
* strings match.
1010
**/
1111
export const getCanonicalTypeName = (state: ParserState, type: ts.Type) => {
12-
const cachedName = state.canonicalTypeNames.get(type);
13-
if (cachedName) {
14-
return cachedName;
15-
} else {
16-
const tmpState = createNewParserState(state.typechecker, state.config);
17-
parseTypeDefinition(tmpState, "TS2PyTmpType", type);
18-
const result = tmpState.statements.join("\n");
19-
state.canonicalTypeNames.set(type, result);
20-
return result;
21-
}
22-
}
12+
const cachedName = state.canonicalTypeNames.get(type);
13+
if (cachedName) {
14+
return cachedName;
15+
} else {
16+
const tmpState = createNewParserState(state.typechecker, state.config);
17+
parseTypeDefinition(tmpState, "TS2PyTmpType", type);
18+
const result = tmpState.statements.join("\n");
19+
state.canonicalTypeNames.set(type, result);
20+
return result;
21+
}
22+
};

src/config.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
export type Ts2PyConfig = {
3-
nullableOptionals?: boolean;
4-
}
2+
nullableOptionals?: boolean;
3+
};

src/index.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import path from "path";
55
import { program } from "@commander-js/extra-typings";
66
import { typeScriptToPython } from "./typeScriptToPython";
77
import { Ts2PyConfig } from "./config";
8-
import { readFileSync } from "fs";
98

10-
const compile = (fileNames: string[], config: Ts2PyConfig & {strict?: boolean}) => {
9+
const compile = (
10+
fileNames: string[],
11+
config: Ts2PyConfig & { strict?: boolean },
12+
) => {
1113
const program = ts.createProgram(fileNames, {
1214
noEmit: true,
1315
allowJs: true,
@@ -23,18 +25,24 @@ const compile = (fileNames: string[], config: Ts2PyConfig & {strict?: boolean})
2325
.map((fn) => path.relative(fn, f.fileName) === "")
2426
.reduce((a, b) => a || b),
2527
);
26-
const transpiled = typeScriptToPython(program.getTypeChecker(), relevantSourceFiles, config)
28+
const transpiled = typeScriptToPython(
29+
program.getTypeChecker(),
30+
relevantSourceFiles,
31+
config,
32+
);
2733
console.log(transpiled);
28-
}
34+
};
2935

3036
program
3137
.name("typescript2python")
3238
.description("A program that converts TypeScript type definitions to Python")
33-
.option("--nullable-optionals", "if set, optional entries in dictionaries will be nullable, e.g. `NotRequired[Optional[T]]`")
39+
.option(
40+
"--nullable-optionals",
41+
"if set, optional entries in dictionaries will be nullable, e.g. `NotRequired[Optional[T]]`",
42+
)
3443
.option("--strict", "Enable all strict type-checking options.")
3544
.arguments("<input...>")
3645
.action((args, options) => {
37-
compile(args, options)
46+
compile(args, options);
3847
})
39-
.parse(process.argv)
40-
48+
.parse(process.argv);

src/newHelperTypeName.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
import { ParserState } from "./ParserState";
22
import ts from "typescript";
3-
import { createHash } from "node:crypto"
3+
import { createHash } from "node:crypto";
44
import { getCanonicalTypeName } from "./canonicalTypeName";
55

66
export const newHelperTypeName = (state: ParserState, type: ts.Type) => {
77
// to keep helper type names predictable and not dependent on the order of definition,
88
// we use the first 10 characters of a sha256 hash of the type. If there is an unexpected
99
// collision, we fallback to using an incrementing counter.
10-
const fullHash = createHash("sha256").update(getCanonicalTypeName(state, type));
10+
const fullHash = createHash("sha256").update(
11+
getCanonicalTypeName(state, type),
12+
);
1113
// for the short hash, we remove all non-alphanumeric characters from the hash and take the
1214
// first 10 characters.
13-
let shortHash = fullHash.digest("base64").replace(/\W/g, '').substring(0, 10);
14-
if (state.helperTypeNames.has(shortHash) && state.helperTypeNames.get(shortHash) !== type) {
15+
let shortHash = fullHash.digest("base64").replace(/\W/g, "").substring(0, 10);
16+
if (
17+
state.helperTypeNames.has(shortHash) &&
18+
state.helperTypeNames.get(shortHash) !== type
19+
) {
1520
shortHash = "HelperType" + state.helperTypeNames.size.toString();
1621
} else {
1722
state.helperTypeNames.set(shortHash, type);

src/parseExports.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import ts from "typescript";
22
import { ParserState } from "./ParserState";
33
import { parseTypeDefinition } from "./parseTypeDefinition";
4-
import { Ts2PyConfig } from "./config";
54

65
export function parseExports(state: ParserState, sourceFile: ts.SourceFile) {
76
for (const statement of sourceFile.statements) {

src/parseInlineType.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,25 @@ export const tryToParseInlineType = (
1919
globalScope?: boolean,
2020
): string | undefined => {
2121
const known = state.knownTypes.get(type);
22-
22+
2323
if (known !== undefined) {
2424
return known;
2525
} else if (type === state.typechecker.getTrueType()) {
2626
state.imports.add("Literal");
27-
return "Literal[True]"
27+
return "Literal[True]";
2828
} else if (type === state.typechecker.getFalseType()) {
2929
state.imports.add("Literal");
30-
return "Literal[False]"
31-
} else if (type === state.typechecker.getAnyType() || ((type.flags & TypeFlags.Unknown) !== 0)) {
30+
return "Literal[False]";
31+
} else if (
32+
type === state.typechecker.getAnyType() ||
33+
(type.flags & TypeFlags.Unknown) !== 0
34+
) {
3235
state.imports.add("Any");
3336
return "Any";
34-
} else if (type.getFlags() & (ts.TypeFlags.TypeParameter | ts.TypeFlags.TypeVariable)) {
37+
} else if (
38+
type.getFlags() &
39+
(ts.TypeFlags.TypeParameter | ts.TypeFlags.TypeVariable)
40+
) {
3541
// we don't support types with generic type parameters
3642
return `object`;
3743
} else if (type.isLiteral()) {
@@ -66,6 +72,9 @@ export const tryToParseInlineType = (
6672
// there is no way to represent template literals in Python,
6773
// so we fallback to string
6874
return "str";
75+
} else if (type.flags & TypeFlags.ESSymbol) {
76+
state.imports.add("Any");
77+
return "Any";
6978
} else {
7079
// assume interface or object, we need to create a helper type
7180
if (!globalScope) {

0 commit comments

Comments
 (0)