309 karma · joined August 10, 2016
I think it's the opposite. It will be a net negative, since people will now run TS by default without type checking. Wasting so much time chasing weird runtime errors - just to end up running the full blown TSC type checking again. They will also write very different TS now, trying to workaround the limitation and arguably very useful features like Enums, constructor properties, etc. This has real negative effects on your codebase if you rely on these, just because Node chose to support only a subset.
It's interesting to see the strategy now and to see people even gaslighting people into believing no type checks and less features is a good thing. All just because of one root cause - TSC being extremely slow.
They know they can skyrocket adoption by limiting the language. That's the reason they regret it. This is just a strategy to increase adoption. Not because they are bad features. They are in fact very useful, and you should not stop using them just because your favorite runtime decided to go the easy way and only supporting a subset of TS by stripping types. You should rather switch the runtime instead of compromising your codebase.
I think running TS without type checks is almost entirely pointless.
That just doesn't make sense. Yes, you can wait for your editor in your current open file, if you are lucky and the change in the open file doesn't break anything downstream in another file that is not yet open. In best case you have such simple code that nothing breaks, and in worst case, you have to still run it with type-checking - on top of running it in type-stripping-mode, because you got weird errors in runtime. This is a net negative.
This whole situation is there because we are trying to workaround the slow TSC. It's not a feature, it's something we actively work around. We try to whitewash now the obviously less useful "solution" of running code without its core features enabled: type checking. To me this is insane.
How useful is it exactly that you accept to not use DX improving syntax like constructor properties, enums, etc? To me, someone who uses these features _a lot_, this would be a terrible trade. Seems more like people push this out of ideology and because TS is never going to be part of node itself (since its implementation is just way too slow)
This will unfortunately drive people towards using TS only as a linter, and not use its powerful features that are inherently impossible to implement with just type stripping.
[0] [url-redacted] [1] [url-redacted]
Prisma's DSL has no syntax for validation constraints, so even with openAPI generators it's incomplete.
Let's say you build a little user management app and need a `User` type. So you define one:
interface User {
id: number;
username: string;
created: Date;
email: string;
}
If you want to build a REST API that returns that user, you can just do that: router.get('/user/:id', (id: number & Positive): User => {
//...
});
Deepkit automatically serialises the object into JSON using the type information in `User`.You want to accept a User object for creating a user in the database? No problem:
router.post('/user', (user: User): User => {
//...
});
You probably want to enrich the interface with additional constraints: interface User {
id: integer & Positive;
username: string & MinLength<3> & MaxLength<32>;
created: Date;
email: Email;
}
And with that the framework automatically validates all incoming requests against the User object and its containing validation constraints. It also deserialises it automatically from JSON for example. If the `User` is a class, it instantiates a class instance.But you don't want to require all fields, like id and created should be set by the server:
router.post('/user', (user: Omit<User, 'id' |'created'>): User => {
//...
});
This works equally well. And the best part: you get API documentation for free with the Deepkit API Console, just like you know from Swagger UI.Ok, but we need to save the User in our database, right? We do not need to duplicate the User in yet another language like with Prisma. Just re-use the User interface and annotate the fields.
interface User {
id: integer & PrimaryKey & AutoIncrement;
username: string & MinLength<3> & MaxLength<32> & Unique;
created: Date;
email: Email & Unique;
}
We still use the very same interface, but have added additional meta-data so you can use that exact same type now also for the ORM. router.get('/user/:id', async (id: number & Positive, db: Database): Promise<User> => {
return await db.query<User>().filter({id}).findOne();
});
Next, let's go to the frontend. We obviously have to request the data from our rest API. We can just do that and reuse the `User` interface once again. const userJson = await fetch('/user/2');
const user = cast<User>(userJson);
`cast` automatically validates and deserialises the received JSON. We import `User` wherever needed and this works because the meta-data is not tightly coupled to any library, so you won't pull in for example ORM code just because you use database meta-data. You can literally use TypeScript's powerful type-system to your full advantage in many small to super complex use-cases and let the framework handle all the validation, serialisation, and database stuff.And like that you are able to reuse types everywhere: From database to http router, configuration, RPC, API documentation, dependency injection, message broker, frontend, and more. That's not possible in this form in any other framework or when you combine lots of third-party libraries and glue them manually together.
Deepkit separated the functionality in libraries which would allow you to use their features in Fastify and Prisma, too, but that would mean you lose one of the biggest advantage of all: Reusing types.