英文:
Type generation tool is not correctly handling nullable fields in TypeScript
问题
I'm building a code generation tool that takes in an input file of my database schema as an interface and generates smaller types from that.
Input
export interface Database {
public: {
Tables: {
profiles: {
Row: {
first_name: string | null;
id: string;
last_name: string | null;
};
};
};
};
}
Expected Output
export type Profile = {
first_name: string | null;
id: string;
last_name: string | null;
};
Actual Output
export type Profile = {
first_name: string;
id: string;
last_name: string;
};
I'm having trouble capturing the null
parts of my output when generating my types.
What I've currently got
const project = new Project({
compilerOptions: {
allowSyntheticDefaultImports: true,
esModuleInterop: true,
module: ModuleKind.ESNext,
target: ScriptTarget.ESNext,
},
});
const sourceFile = project.addSourceFileAtPath(typesPath);
// Find the 'Tables' type alias
const databaseInterface = sourceFile.getInterfaceOrThrow('Database');
const publicProperty = databaseInterface.getPropertyOrThrow('public');
const publicType = publicProperty.getType();
const tablesProperty = publicType
.getApparentProperties()
.find((property) => property.getName() === 'Tables');
const tablesType = project
.getProgram()
.getTypeChecker()
.getTypeAtLocation(tablesProperty.getValueDeclarationOrThrow());
const tablesProperties = tablesType.getProperties();
const types: string[] = [];
for (const table of tablesProperties) {
const tableName = table.getName();
types.push(...generateTypes(table, tableName));
}
...
export function generateTypes(table: Symbol, tableName: string): string[] {
// Get the table type
const tableType = table.getTypeAtLocation(table.getValueDeclarationOrThrow());
// Find the 'Row' property within the table type
const rowProperty = tableType.getProperty('Row');
// Get the type of the 'Row' property
const rowType = rowProperty.getTypeAtLocation(
rowProperty.getValueDeclarationOrThrow()
);
const rowTypeString = rowType.getText();
const types: string[] = [];
types.push(
`export type ${toTypeName(tableName)} = ${rowTypeString};`,
...
);
return types;
}
I've tried a lot of variations regarding what I've posted above, but every single time I run my generate function, I can't get it to print | null
for those scenarios where properties could be null
.
Using ts-morph
v18.
英文:
I'm building a code generation tool that takes in an input file of my database schema as an interface and generates smaller types from that.
Input
export interface Database {
public: {
Tables: {
profiles: {
Row: {
first_name: string | null;
id: string;
last_name: string | null;
};
};
};
};
}
Expected Output
export type Profile = {
first_name: string | null;
id: string;
last_name: string | null;
};
Actual Output
export type Profile = {
first_name: string;
id: string;
last_name: string;
};
I'm having trouble capturing the null
parts of my output when generating my types.
What I've currently got
const project = new Project({
compilerOptions: {
allowSyntheticDefaultImports: true,
esModuleInterop: true,
module: ModuleKind.ESNext,
target: ScriptTarget.ESNext,
},
});
const sourceFile = project.addSourceFileAtPath(typesPath);
// Find the 'Tables' type alias
const databaseInterface = sourceFile.getInterfaceOrThrow('Database');
const publicProperty = databaseInterface.getPropertyOrThrow('public');
const publicType = publicProperty.getType();
const tablesProperty = publicType
.getApparentProperties()
.find((property) => property.getName() === 'Tables');
const tablesType = project
.getProgram()
.getTypeChecker()
.getTypeAtLocation(tablesProperty.getValueDeclarationOrThrow());
const tablesProperties = tablesType.getProperties();
const types: string[] = [];
for (const table of tablesProperties) {
const tableName = table.getName();
types.push(...generateTypes(table, tableName));
}
...
export function generateTypes(table: Symbol, tableName: string): string[] {
// Get the table type
const tableType = table.getTypeAtLocation(table.getValueDeclarationOrThrow());
// Find the 'Row' property within the table type
const rowProperty = tableType.getProperty('Row');
// Get the type of the 'Row' property
const rowType = rowProperty.getTypeAtLocation(
rowProperty.getValueDeclarationOrThrow()
);
const rowTypeString = rowType.getText();
const types: string[] = [];
types.push(
`export type ${toTypeName(tableName)} = ${rowTypeString};`,
...
);
return types;
}
I've tried a lot of variations regarding what I've posted above but every single time I run my generate function I can't get it to print | null
for those scenarios where properties could be null
.
Using ts-morph
v18.
答案1
得分: 2
打开 strictNullChecks
编译选项:
const project = new Project({
compilerOptions: {
allowSyntheticDefaultImports: true,
esModuleInterop: true,
module: ModuleKind.ESNext,
target: ScriptTarget.ESNext,
strictNullChecks: true, // <-- 这里
},
});
否则,类型检查器将忽略联合类型中的 undefined/null,并认为所有类型都不可为空(ts-morph 使用与 TypeScript 编译器中找到的相同默认值)。
英文:
Turn on the strictNullChecks
compiler option:
const project = new Project({
compilerOptions: {
allowSyntheticDefaultImports: true,
esModuleInterop: true,
module: ModuleKind.ESNext,
target: ScriptTarget.ESNext,
strictNullChecks: true, // <-- this
},
});
Otherwise the type checker ignores undefined/null in union types and thinks all types are not nullable (ts-morph uses the same defaults found in the typescript compiler).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论