TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

TypeScript and SQL: Six Ways to Bridge the Divide

2 点作者 danvk超过 1 年前

1 comment

shortrounddev2超过 1 年前
I have personally come to the conclusion that typescript should not be used for writing a backend. The lack of RTTI means that you have to either write a TON of verbose code mapping Typescript class fields (note: different than ES6 classes, which would be more useful in this regard) to SQL statements.<p>What this means in practice is using ORM frameworks which require you to put decorators (which are still somehow &quot;experimental&quot; despite all major frameworks relying on them) on your class fields to generate sql commands.<p>But you also need to handle user input, and validate it. You can use JSONSchemas in some frameworks (fastify), but there&#x27;s no really good way to generate these automatically yet, and you&#x27;ll need to update them as you add more fields. This is most easily done through (a lot) more decorators<p>Additionally, because there&#x27;s no RTTI, you can&#x27;t rely on the typescript operators like keyof to generate other fields at runtime (only at compile time). Let&#x27;s say you have a query interface you want to write. You can provide the name of a field to filter by, along with a value. This is a JSON POST Body. Maybe you have a model like:<p><pre><code> export class BlogPost { title: string; body: string; postedOn: Date; postedBy: string; } </code></pre> To query the query interface, you&#x27;ll need to declare every field again independently, because you can&#x27;t apply class validators to the results of keyof operators:<p><pre><code> export class QueryBlogPost { @ApiProperty() @IsString() @IsOptional() title?: string; @ApiProperty() @IsString() @IsOptional() body?: string; @ApiProperty() @IsString() @IsDateString() postedOn?: Date; @ApiProperty() @IsString() @IsOptional() postedBy?: string; } </code></pre> let&#x27;s say you want to specify all the fields which you want returned, so you can limit the size of the response (perhaps you don&#x27;t want to return the blog post body in a search request). Again, you cannot use keyof here to get a list of valid fields at runtime. Instead, you need to specify them manually:<p><pre><code> export class QueryBlogPost { @ApiProperty() @IsString() @IsOptional() title?: string; @ApiProperty() @IsString() @IsOptional() body?: string; @ApiProperty() @IsString() @IsDateString() postedOn?: Date; @ApiProperty() @IsString() @IsOptional() postedBy?: string; @ApiProperty() @IsOptional() @IsEnum([&quot;title&quot;, &quot;body&quot;, &quot;postedOn&quot;, &quot;postedBy&quot;], {each: true}) fields?: string[] } </code></pre> If you add a new field, remember to manually add that field to your enum<p>Don&#x27;t forget non-primitive types: if you have a nested class, you need to add multiple decorators for that, since you can&#x27;t get the constructor or type of the class at runtime:<p><pre><code> export class Author { @ApiProperty() @IsString() firstName: string; @ApiProperty() @IsString() lastName: string; } export class QueryBlogPost { &#x2F;&#x2F;... @ApiProperty() @ValidateNested() @Type(() =&gt; Author) @IsOptional() author?: Author; } </code></pre> not to mention if it&#x27;s an array, in which case every class needs @IsArray(), @ValidateNested({each: true}) added to it<p>Plus all the documentation decorators which add example queries, queries which take arrays (for operators such as &quot;any&quot; or &quot;in&quot;.<p>This isn&#x27;t to mention return type DTOs, or the decorators for the ORM.<p>Typescript is a frontend language. It is good for creating data. It is very bad for receiving it. With typescript as a backend, you end up writing the same code 5 times which introduces bugs. Do not write typescript backends just because your junior devs are afraid to learn Java or C# or a language more suited for backend development
评论 #37324940 未加载