You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am trying to create a type tree from extracted types in a typescript file. I am using bun and ts-morph I can handle different types, like primitives, and some objects. But when trying to handle Records, I cannot get the types that compose the record. To give an example, this is the test I want the code to pass:
import { expect, test } from "bun:test";
import createTypeTree from "../src/create-type-tree";
test.only("handle complex Records", () => {
const sourceCode = `
type Id = string;
type Value = {a: number, b: string}
type MyRecord = Record<string, number>;
`;
const result = createTypeTree("temp.ts", sourceCode);
expect(result).toStrictEqual({
MyRecord: { ["string"]: { a: "number", b: "string" } },
Id: "string",
Value: { a: "number", b: "string" },
});
});
This is a simplified and reproducible version of my code
import { Project, Type } from "ts-morph";
type Result = Record<string, unknown>;
export default function createTypeTree(
filePath: string,
testCode?: string,
configFile?: string
): Result {
const project = new Project({
tsConfigFilePath: configFile,
skipAddingFilesFromTsConfig: true,
});
const sourceFile = !testCode
? project.addSourceFileAtPath(filePath)
: project.createSourceFile(filePath, testCode);
const result = [
...sourceFile?.getInterfaces(),
...sourceFile?.getTypeAliases(),
].reduce((acc, current) => {
const name = current.getName();
acc[name] = handleTypes(current.getType());
return acc;
}, {} as Result);
return result;
}
function handleTypes(t?: Type) {
return isPrimitive(t) ? handlePrimitive(t) : handleNotPrimitive(t);
}
function isPrimitive(t?: Type): boolean {
const isString = t?.isString() || t?.isStringLiteral();
const isBoolean = t?.isBoolean() || t?.isBooleanLiteral();
const isNumber = t?.isNumber() || t?.isNumberLiteral();
const isNullish = t?.isNullable();
return Boolean(isNumber || isString || isBoolean || isNullish);
}
function handlePrimitive(t?: Type) {
switch (true) {
case t?.isNumberLiteral(): {
return Number(t?.getText());
}
case t?.isBooleanLiteral(): {
return t?.getText() === "true";
}
default: {
return t?.getText();
}
}
}
function handleNotPrimitive(t?: Type) {
// Here the important part. Record is object but returns {}.
// I want to handle Records here.
// I did not include tuples or arrays for simplicity
if (t?.isObject()) {
return handleObject(t);
}
return "Type not handled";
}
function handleObject(t?: Type) {
const obj: Record<string, unknown> = {};
t?.getProperties().forEach((prop) => {
const name = prop?.isOptional() ? prop?.getName() + "?" : prop?.getName();
const innerDeclaration = prop.getDeclarations();
innerDeclaration.forEach((p) => {
const innerType = p.getType();
obj[name] = handleTypes(innerType);
});
});
return obj;
}
How can I extract the types inside a record?
The text was updated successfully, but these errors were encountered:
I am trying to create a type tree from extracted types in a typescript file. I am using bun and ts-morph I can handle different types, like primitives, and some objects. But when trying to handle Records, I cannot get the types that compose the record. To give an example, this is the test I want the code to pass:
This is a simplified and reproducible version of my code
How can I extract the types inside a record?
The text was updated successfully, but these errors were encountered: