16 ms·
TypeScript please give us reflection/runtime types
- marcelr 3y agoPlease no, typescript is already complex as all hell.
- kazinator 3y agoAnything run-time has to come from JavaScript. TypeScript is syntactic expansion layer over JavaScript. "C preprocessor, please give me arrays that know how big they are at run-time. Oh, and access to the calling function's local variables!" "Common Lisp defmacro, give me continuations usable anywhere!" A macro layer can bring you the pie in the sky, but only (1) at some nonozero cost and (2) with additional representations that are not understood by regular code that is not in that framework. Suppose a TypeScript type object is attached to every run-time object created in TypeScript. Firstly, those objects become more bloated and expensive to construct. [Edit: not really: all objects of the same type can have a pointer to the same meta-data which is created once]. They will need run-time support in their execution environment in order to have those type representations. Objects not created by TypeScript-generated code will not have anything like that attached to them, so places in the system where the two domains interoperate won't be able to rely on reflection; it will need a fallback for objects that don't do reflection. I think serialization can be done without reflection. Because at the time when the static language is being processed, you could annotate certain types as requiring serialization. Then for those types, TypeScript would generate the marshaling routines. Generating marshaling stubs from an interface language has been done in the C world for decades. It doesn't require any run-time types. The generated marshaling stubs just know how to walk objects of the type that they handle, and that's it. It looks like in TypeScript, serialization is just punted to JSON, which is inadequate because when we are deserializing, we want to check that the JSON blob has a type and shape compatible with the TypeScript-level type. (Or even for that that type to be inferred in some way.) There are some libraries that try to do something in this direction like ts-serializer. I think it's something you really want in TypeScript itself. Basically round up the half-dozen or so use cases for reflection, and provide for all of them somehow without actual reflection. It's an X/Y problem. People really want to do Y (e.g. serialization), and believe that they must first solve X (have metadata in objects for reflection).
- kazinator 3y agoFairly recently I built a C library for object serialization, based on run-time reflection. Run-time reflection is not necessary to the task and makes it perform worse than a code-generating solution. The run-time reflection approach is good in one way: it doesn't add tooling to the project. All the modules that use serialization have to make a bunch of tedious API calls to build the type object which represents the C structure. This is created once and stashed in a global variable. Then it is used as a parameter when serializing and deserializing. There is a performance impact because the marshaling code is interpreting the type object; it recursively walks the type object, and in parallel it walks the C object to extract or stuff material. A generative approach would just write a serialization and deserialization stub. There would be no need for any type object to be walked at run-time. No need to construct such objects at startup and no need to carry the library for that. But there would be some tool which itself has to be compiled (for the build machine, not the embedded targets), and then some Makefile steps to run that tool on some interface files. The thought of inflicting that one the project made me go yuck. A third possibility is to have the run-time type info objects, and add JIT. Why do something easy, like a code generation tool called out of Makefile, when you can do something hard and nonportable?
- eyelidlessness 3y agoThis comes up so often, and every time I wonder how much the people who want it have a shared understanding of what it is they want. I realize this is reiterating a point that TS team members have already made, but I’m coming from a different perspective: actually having built higher level tooling on top of one of the solutions mentioned in the post, and having built a fairly mature prototype of another solution from the ground up to address problems none of the existing offerings solve. My use case isn’t particularly outlandish, I can even imagine it being non-niche if I ever get around to publishing it. But it’s also pretty far afield from any of the existing solutions: platform-agnostic documentation as a core/foundational principle. My original work implemented JSON Schema documentation on top of io-ts, and added some runtime and type level functionality to support that. But my vision for a hypothetical successor is that - the documentation standard itself (whether JSON Schema, OpenAPI, or any other underlying format) should be the underlying primitive - the underlying format should be composable to produce APIs which are just as user friendly (ie users shouldn’t have to muck around with the doc format unless they have a really specific use case, and even then they should still be able to compose the parts they’re not concerned with) - no additional build time codegen tooling: define a schema once, its type is inferrable from the definition without a compiler extension or IDE config, its documentation is a plain function call executable in any standard runtime to resolve what’s composed This is all very achievable in TypeScript as-is. But it’s way out of scope from what I imagine any first class thing would or should be. And sure, if such first class thing existed, that wouldn’t make my thing any less achievable. But here’s what I think it would do: 1. Disincentivize usage by users who prefer the first class thing with type syntax as the primary authoring mechanism. 2. Incentivize me to cave on tooling to accommodate that. 3. Piss people off because “we wanted less tooling not more”. 4. Recurse into this same debate. I’d personally prefer the status quo. Even if that means rehashing the same debate every few months, at least it’s at a recursion depth that’s manageable and doesn’t have countless other sets of unintended consequences.
- chmod775 3y agoSince it's not explicitly listed there, I feel I should shout out David Blass and his incredibly cool ArkType project[1]. It's typescript wizardry. He sometimes (used to?) streams himself working on twitch and it's a really comfy place to hang out.[2] [1] https://github.com/arktypeio/arktype https://github.com/arktypeio/arktype [2] https://www.twitch.tv/arktypeio https://www.twitch.tv/arktypeio
- yewenjie 3y agoHow complete is arktype actually? The README says a lot of the syntax is yet to be developed, and don't even get me started on the horror of the docs site.
- chmod775 3y agoUntil a short while ago it was still very much work in progress. Right now a lot of work seems to be going into getting a 1.0 release out of the door (the current one is still marked alpha).
- RussBrown00 3y agounpopular opinion, but this just fosters my opinion that TS people just don't understand JS at all. I wish TS would just die (another currently unpopular opinion). If you want runtime type safety, go use a different language and stop trying to ruin JS, it's already the messed up crazy cousin and it doesn't need to be in-bread anymore, it's perfect the way it is!
- imbnwa 3y agoOnly writer I know who discusses pure JS patterns that embrace those its dynamism is Raganwald Braithwaite[0]. For example, most people I know would call this hacky code[1], when this is just design patterns in idiomatic, non-Java/C#-constrained JavaScript. The truth, most devs desire intellisense and/or theorycrafting that comes with static types and compilers. [0]https://raganwald.com/ https://raganwald.com/ [1]https://raganwald.com/2014/04/10/mixins-forwarding-delegatio https://raganwald.com/2014/04/10/mixins-forwarding-delegatio...
- cannabis_sam 3y agoThis is just the desperation that comes with poor understanding. The strength of a type system should ideally be that you could confidently execute the underlying code even with full type erasure, and while I realize that TS has already sacrificed this to some extent, adding reflection/runtime “types” would just further degrade the value of TS. No thanks! If you want this, compile java to JS or something equally hamfisted…
- mk81 3y ago[dead]
- nsonha 3y agoIt would be nice but the problem is not that big of a deal if you use any of the community libraries they mentioned.
- moomoo11 3y agoUse zod
- osigurdson 3y agoReflection is terrible. The only thing that is worse is creating something like reflection in imperative code in languages that do not have it.
- deleted 3y ago[deleted]
- deleted 3y ago[deleted]
- lf-non 3y agoDeepkit (listed in the article) is a fascinating project and really deserves to be more popular. It also demonstrates that what is being asked for is actually practical. https://deepkit.io/ https://deepkit.io/
- dSebastien 3y agoRuntime type checking is an explicit non-goal of TS: https://www.dsebastien.net/2020-04-25-typescript-non-goals/ https://www.dsebastien.net/2020-04-25-typescript-non-goals/
- haskman 3y agoA lo of people in this thread seem to be misunderstanding what is being asked for. There is no runtime reflection needed. What is really needed is - 1. A way to get a value that represents the type of any statically known type (i.e. known at compile time). 2. A way to compare two typereps for equality. 3. A way to convert between types if the typereps are equal. This is basically the equivalent of the `Typeable` class in Haskell and PureScript (https://hackage.haskell.org/package/base/docs/Data-Typeable.html https://hackage.haskell.org/package/base/docs/Data-Typeable....). Both Haskell and PureScript erase types at runtime, so it is possible to do without adding a runtime to TypeScript as well.
- gizmolo 3y agoFuture ECMAScript iterations will include types and then hopefully TypeScript can take advantage of that to implement reflection and other cool things
- ouraf 3y agoCan anyone do a "explain lime I'm five" summary of the problem and how the solution would work when typescript is converted down to JavaScript again so the interpreter takes it? Looking from the top it seems like it would add more complexity (and potentially new bugs or exceptions) than it could make things faster and safer. IF typescript was 100% its own thing and not built on top of JS, it would make complete sense to do it, but with a js engine below it...
- jpc0 3y agoStated differently. Our JavaScript bundles are not large enough or slow enough. Could you please make it so we can ship even more data to the client and add more branching so we can give our customers an even worse experience. You want reflection, use a language that has it and ship webassembly to the client, it will likely be significantly more performant than adding even more bloat to what is already needing to run in the JS interpreter.
- dvt 3y agoI dunno, this seems like it would be out of scope for something like TS proper (there's already been a ton of feature creep, anyway). Reflection is generally implemented via runtimes, which can be very clunky. Is it really worth doing this in JS? Tooling already seems too bulky as is.
- MrResearcher 3y agoTypescript already kind of has it, it's just they got it backwards. One needs to define their types as a const, like this one: ``` [{ type: Number, name: "field1" }, { type: String, name: "field2" }] as const ``` and then use Typescript magic to convert it into the fully fledged Typescript type. Yes, it's annoying, but it's more flexible.
- gloryjulio 3y agoU just need a library to enable this to reduce the boilerplate. I don't see how that's impossible
- asherah 3y agothis wouldn't work for interfaces, or more complicated types
- epolanski 3y agoThis is as useful as vue 2's prop types: very little.
- paulddraper 3y agoBetter title: TypeScript please give us reflection/runtime types AFAIK the best current solution is emitlDecoratorMetadata. [1] [1] https://www.typescriptlang.org/tsconfig#emitDecoratorMetadata https://www.typescriptlang.org/tsconfig#emitDecoratorMetadat...
- dang 3y agoOk, we'll add that bit to the title above. Thanks!
- rcme 3y agoThere are good typed deserialization libraries. Personally, I prefer runtypes but there are options.
- decs 3y agoAgree, zod, arktype, and typia are impressively easy to use! Though, I feel that this environment created a different problem of spreading developers into multiple solutions. So for lib devs like me, we end up having to choose between coupling with a single validation lib or managing support for multiple (like tRPC does). To address that, I ended up doing a reusable lightweight lib that wraps that logic for supporting multiple: https://typeschema.com https://typeschema.com
- code_biologist 3y agoThanks for the lib! I'm always charmed to come across such a concrete example of the fundamental theorem of software engineering: "We can solve any problem by introducing an extra level of indirection."
- andix 3y agoThere is a good reason for not doing this. Typescript would become some kind of runtime on top of JavaScript. A new language that compiles to JavaScript. Currently TS is only JavaScript with type annotations. There are many languages that compile to JavaScript. Pick one of them and use it! And I have the feeling, that people who want runtime typed Typescript would rather like to write Java/OOP style code instead of JavaScript. But JavaScript is a dynamically typed language, and that's also nice. Be happy with what you have!
- shortrounddev2 3y agoThe reason we want typescript to have java-like features is because we work on teams which have decided, outside of our control, that we are going to write our backend in JS/TS simply because it's easier for the bootcamp grads to transition to backend since they already know JS on the frontend. If we wrote our backend in Java, it would require the bootcamp grads to learn a new language, which they're not prepared to do. Choosing typescript or javascript on the backend is not about choosing the right tool for the job (because they are objectively not the right tool for backend development). It is mostly about minimizing the cost of our labor sourcing As such, RTTI would make typescript go from a compromise language (we use it because we are stuck in the JS ecosystem, not because it's a good tool) to a legitimately useful backend language (We use it because it has the right features for the use-case) If I could choose what language we use on the backend, I would leave the JS ecosystem entirely and write everything in .Net. But it's difficult to find .Net developers since every bootcamp these days produces react developers
- andix 3y agoSo you want TypeScript to be Java, but you don't want to use Java, because your developers only know TypeScipt. Sounds like an unsolvable problem.
- shortrounddev2 3y agoThe solution is to pile features onto typescript that were never intended to be there, the same way we have done with Javascript, HTML, CSS, and HTTP. None of these things are pure, and all of them have been ravaged by competing interests and committees who were all making financially driven decisions when writing the standards. It would be best to abandon javascript and typescript as backend languages. I don't mind them on the frontend because a typescript compiler is useful when the application you're writing is originating data and not receiving it. And javascript does DOM manipulation admirably. However, we live in a world where humans are more expensive than computers. If I had my way, we'd write C# backends and Angular/Typescript frontends, but that's not the world we live in. Everything has to be JS because most people employed as "software engineers" are not truly very good at their jobs
- Waterluvian 3y agoAbove all of what I write below, I think that this is a very valid issue for discussion and debate. I don't think there's one objective correct answer. So this isn't me dictating what TypeScript shalt be. TypeScript is an entirely optional layer on top of JavaScript, with the exception of `Enum` that emits an object, many of which see as a mistake. You don't even have to "transform" TS code to get JS: you just have to delete the typings. The rest is just JS. Unless you want to depart heavily from this principle, which I think is crucially important so long as there's still human-maintained JS code out there, what I think they're asking for is a library to take the types and write serializers/validators for. Which there are many of. So I think the real request is to make the one canonical choice out of a field of many choices, which I also agree with the spirit of. But is that really in scope for the TypeScript project? What I personally don't want is runtime reflection for TypeScript. Or at least, not a core part of the language. Because I like that TypeScript is just for compilation and at runtime you just have JavaScript, without any sort of abstraction layer that turns JS into some sort of intermediate representation with overhead or more indirection for debugging. I cherish the fact that even without source mappings, my output JS is perfectly legible and debuggable.
- eyelidlessness 3y ago> with the exception of `Enum` that emits an object, many of which see as a mistake There are other exceptions, most of which are considered mistakes as well, the most obvious which come to mind being `module` and `namespace` as runtime constructs. But I’m fairly sure these have been primarily used by TypeScript itself for at least a few years, and even they recently migrated away. Another one that comes to mind is, I believe, actually pretty popular: what they refer to as “parameter properties”, ie class members whose types are defined in a constructor’s parameters. These seem to have escaped controversy because they eliminate a lot of redundant boilerplate, and generally behave in obvious ways (at least as obvious as their redundant boilerplate JS equivalents).
- syspec 3y ago> You don't even have to "transform" TS code to get JS Sure if you consider the whole language, typings
- lucidone 3y agoOP and those who feel a similar sentiment should give C# a shot, it's what they want regardless of whether they know it or not.
- shortrounddev2 3y agoI love C#. At work, when I write standalone tools, I always do them in C#. My boss tolerates this since I'm usually the only one using them. But I don't get to choose what our backend is written in
- anonzzzies 3y agoYep, but you want to write frontend with it then. Blazor (or whatever liveview-like implementation) or wasm might fix that.
- orangepanda 3y agoI vaguely remember one of typescripts developers stating that if they had to start it all over again, enums would not be added; as enums are the only thing emitting runtime code. Typescript does not change runtime behaviour, there is no special typescript {#if}
- ragnese 3y ago> I vaguely remember one of typescripts developers stating that if they had to start it all over again, enums would not be added; as enums are the only thing emitting runtime code. It's true. I don't remember if that was the only/main reason they said that, but that was definitely one of the things. I find that a weird sentiment, though, because TypeScript has a couple of other features that are not just "JavaScript + type annotations". Namespaces is one. It also has a syntactic sugar for defining class properties in the constructor arguments. And it had that experimental decorator feature for a long time, but I never used it, so I don't know much about it. It also has the "`this` parameter" syntax for methods/functions, which does disappear at compile time, but still looks and feels like more than just a JavaScript function with type annotations.
- wvenable 3y agoAlthough namespaces are not deprecated they are not recommended anymore -- much for the same reasons.
- WorldMaker 3y agoFrom my understanding, namespaces are on the same list with enums of things that the developers regret ever adding to the language but can't take out without breaking old code. Namespaces also at least have the excuse of being a "necessary" jQuery-era "Production pattern" in the land before ESM was standardized and somewhat relating to the similar syntax sugar of import/export when generating AMD, UMD, and CommonJS modules. So too are "experimental decorators" another thing that some of the developers seem to list as massive regrets. That example is even so much worse than namespaces because it wasn't justified by existing patterns used in Production JS at the time and that they even believed that requiring a compile-time flag with the word "experimental" in it would stop developers from using that compile-time flag in anything destined for Production usage. (Seriously, we all should shame the many projects/companies that did that.)
- evmar 3y agoIf anything, the wide range of different approaches to run-time type information listed here is pretty good evidence that there are many different use cases and any approach built in to TS would not cover them all.
- drtz 3y agoThe problem with TypeScript isn't the lack of reflection. The problem is that at runtime its type system is still Javascript in all its glory. Workarounds are just band-aids on the underlying mess at best.
- medler 3y agoI’m mainly a backend programmer, so I know just a little typescript, but I don’t really understand what they’re asking for here. It sounds like they want to serialize and deserialize typescript types automatically? If so, that sounds like a good fit for a library, not something most languages offer. (Please educate me if I’m missing the point)
- shortrounddev2 3y agoThere is currently no good way to automatically validate the object input to a typescript API. In the way that you can simply specify the class of a POST body to a spring boot controller or Asp.Net controller, every class in typescript requires you write the type information twice: once for the typescript compiler, and once again for the runtime deserializer, in the form of decorators. Having to write extra code to make up for a deficiency in your framework, runtime, or language is the definition of code smell. As such: all typescript backends which attempt to properly validate user input are guilty of egregious codesmell. Additionally, because it is impossible to emit these types to the runtime, even in the form of a string naming the type, you cannot validate input to an API using generics. If you have, say, a class which will run a query for a record based on the keys in that record: class Query<T>{ filter: Array<keyof T> }; The typescript compiler can validate if a string in "filter" is, in fact, a key of the class T. However, you cannot write any decorator on this class to make the information of what keys exist on T available at runtime. Therefore, to write such a query interface and validate it at runtime, every record which can be queried with this object must have its own specific "[Record]Query" class written with its own decorators to validate every possible input, usually with the valid keys hardcoded into the decorator. Because there is no real relationship between the class and the runtime validators, this makes validation more error prone, because it relies on either human beings to consistently remember to add new fields to the relevant decorators, or a custom linting tool to be written which basically pre-processes the typescript source using the typescript API. This is, again, writing code to account for the lack of features in the framework. WHY do we put up with this crap? We have had Java and C# for a long time, and they solved these problems a long time ago. Why are we writing Typescript on the backend? The simple answer; it is easier to find javascript developers than it is to find java developers. Bootcamps don't teach Java or C# because there's more react jobs out there. Bootcamp grads are not generally coding enthusiasts and so re-tooling is difficult for them and they don't generally do it for fun. So, we decided to write our backend in Javascript (or Typescript) as a labor decision, not a technology decision.
- moritzwarhier 3y agoVery interesting post to me. There always was the argument that TS should be erasable and carry no runtime information, enums and decorators are a mistake, etc. For what it's worth, I want my production bundle to be as small as possible. Most people use bundlers among TypeScript, which further complicates things. I would love a standard library to e.g. generate type predicate functions from TS types. Taming the beast from this end might even end up useful for things like compilers, no? TS provides a nice mechanism to be strict in the frontend and validate types using runtime code, that is, type predicates. But from a higher level, this has never been enough, and you want to map JSON to TS types using some kind of schema definition. I would love to just be able to pass in a TypeScript type and generate its type predicate at compile time. Unfortunately, this is impossible due to the halting problem. So, a standard solution for the case of a plain serializable JS/JSON object and the according TS interface would be very much welcome. Edit: and all of this is of course about data from external sources (requests, DOM, compiler...). For all of the code and data known at compile time, there is rarely a need to validate types, as they are statically analyzable. So there is a huge scope that TypeScript has to cater to. It includes JS projects where external type definitions often become obsolete and people who code in TS but do not enable strict mode for their own code (that is, disallow "any"). And all of these type defintions have to be interoperable. For API requests, this is basically calling for a default generic REST client, and I agree that would be useful. The REST client could use type predicate functions extensively.
- brundolf 3y ago2¢, having non-runtime types makes code behavior easier to reason about, especially when aggressive type inference is present, and I'd hate to lose it One of the things I don't love about Rust is how type inference affects program behavior in ways that can be really subtle. In Rust's case this is a necessary evil because it doesn't have a dynamic foundation, but TypeScript has done great without that compromise
- dontlaugh 3y agoMaybe controversial, but I think code generation is fine. It work well enough in Go or C#.
- thanksgiving 3y agoI’m not an expert or anything but I sincerely feel like this is barking up the wrong tree. To anyone who works on typescript/JavaScript outside the context of a web browser, you DO NOT matter as far as I am concerned. If I was in control of JavaScript/typescript, I’d give zero attention to your demands. You are not my top priority. Go away. I feel like we are losing focus here. Should JavaScript be an all purpose language? Yes. Should we focus on making a web browser context, also yes. The reason I led with this is that I think it is up to the JavaScript folks and the web browser vendors to include support for this before typescript can change what it emits. Ideally, I’d say wait a couple of years after browser vendors include support to implement this in typescript.
- Eric_WVGG 3y agoI don't understand this comment at all. I mostly work on client-side front-end and am absolutely desperate for better type generation. Zod is making me want to jump out a window right now.
- thanksgiving 3y agoMy comment is simple. Don’t add anything to JavaScript if it does not help in the context of a web browser. Don’t add anything to typescript emitted output if it isn’t in JavaScript.
- colinmcd 3y agoSomething like typebox (that's designed to map one-to-one onto JSON Schema) may be better if codegen is a priority.
- noobdev9000 3y agoModern TS code is hard for me to read and reason, and I use Rust, Haskell, C++. Way too complex for my brain
- epolanski 3y agoWell, as always, this really depends on our the code we read and our background. TypeScript's type system is indeed way more verbose than Haskell's.
- zoogeny 3y agoThis is the perennial problem with language design. Everyone wants something and they even have reasonable grounds to ask for it. I myself have come across moments where some rtti/reflection would have been useful. In those cases I was often able to use branded types. Having something like that built into the language might be nice. But I'd also support TypeScript and JavaScript developers making the choice not to support it ever. IME, working around rtti type code often forces the programmer to come up with a much better approach.
- JohnDotAwesome 3y agoInstead of pleading to the TypeScript gods, why not make a deal with the JavaScript deities? Let's get type-checking into JS! If I want runtime types, I reach for type guards. If I need to do this a lot, then I reach for io-ts or zod and pretty much exclusively write types as validators/codecs/schemas or what-have-you. I don't think TS - as a specification, type-checker, community, or otherwise - needs to concern itself with runtime validation UNLESS JS gets some agreed upon way to do it.
- steve_adams_86 3y agoI know it’s not perfect, but I’m pretty content writing schemas and types as validators with zod and deriving my types from those. That you can derive the types easily and the validation then evolves with your typing is really nice. I’ve worked with people who find it too complicated or they feel like it should be baked into the language, but I’d argue there are so many contentious design choices in these libraries that it might actually be best to be an implementation choice, selected based on a project and its specific needs. Zod has been very good to me though. It’s quite easy to get up and running with, and its API has never gotten in my way when scaling things out. My one complaint is that certain patterns I love, such as runtime validation with zod and deriving types from schemas, doesn’t necessarily always play well with something like pattern matching in ts-pattern. The type definitions behind these libraries are labyrinths, and cases where something seems like it should work won’t always behave as expected. On some level, I do wish these were seamless language level features, though I fully recognize these are selfish desires. But imagine having runtime safety combined with exhaustive pattern matching. I’d be very happy to have that.
- epolanski 3y agoI have huge doubts whether I'd like JS to have it really. I feel like Promises, decorators and the new pipe operator all went into the wrong directions with their implementations.
- esprehn 3y agoHow do you feel like promises went in the wrong direction? (I'd also add modules to your list fwiw, they were designed without taking performance into account.)
- frou_dh 3y agoI was perfectly satisfied with using https://zod.dev https://zod.dev for some runtime data validation, and found it really cool that I didn't have to define some nominal type off to the side and could instead just say what I meant inline using a fluent API.
- william-evans 3y agoAs listed, Typebox is excellent for this use case - it correctly implements the JSON schema spec and allows you to use it to write OpenAPI specifications. At my company we use this to write type-safe handlers & generate our API documentation!
- paxys 3y agoI had to read their problem statement like 4 times to understand what they are asking for. This is exactly why simple, concise writing is essential, and their wall of text is...not it. > I love you. You do amazing work. You are gods among mortals. You have brought JavaScript from the darkness, and given it the warm light of strong typing. Look upon us, the cowering meek masses, and understand that we live in the muck and mire of a world where we are doomed to endlessly crawl on our bellies through the alleys of Github seeking the one true npm. We will forever wonder in the dark, until we have a type reflection model. What even are they getting at? As for their actual ask (runtime type safety), it is probably not going to happen because the TypeScript project has drawn the line at not being an alternate or additive runtime for JavaScript. Their job is simply to compile down to JS code and exit the picture. Whatever happens after that (in V8 or elsewhere) is your own business. > TypeScript Needs to Emit Runtime Type Information This is not possible at all because TypeScript is a compiler. They are really asking for a net new product which has very little to do with the TypeScript that exists today.
- cjdell 3y agoTypeScript does emit runtime type information through enums though.
- tinideiznaimnou 3y ago[flagged]
- RyanCavanaugh 3y agoI'm here and I have no idea what you're talking about with ESM imports. Please log a bug.
- tinideiznaimnou 3y ago[flagged]
- seattle_spring 3y ago
- can16358p 3y agoThis shouldn't happen... unless someone finds a way to do this without a runtime overhead, which naturally seems impossible. If this is done, TS will become something entirely different as it currently doesn't have a runtime: it's a huge-and-smart linter. But that's all about it. No matter how huge, it's a linter. Reflection would imply something beyond that. Even though I absolutely love reflection, I believe it should not be integrated into TS.
- vbezhenar 3y agoIt has nothing to do with any runtime. You just write const personType: Type = typeof(Person); This code gets compiled into const personType = { name: "Person", fields: [ { name: "lastName", type: "string" }, { name: "firstName", type: "string" }, ], } There's no runtime. It's just an object which describes layout of some time. If you would implement validation by hand, you'd come up with absolutely conceptually identical code. Look at any validation libraries out there. The only difference is: you specify types with nice TypeScript language, not with some made-up abomination DSL.
- can16358p 3y agoOh okay I was thinking of more of a runtime-code-emitting-dynamically kind of thing. If it's the way you've shown it'd be great!
- mrkeen 3y agoNo runtime necessary, if I understand the problem. Input is bytes. Bytes will never carry their type information (and if they did, you couldn't trust them). So the type information needs to be used in the Deserialiser, not its input. To get typed deserialisation of Foo, the compiler needs to generate a FooDeserialiser automatically for you. The compiler can't depend directly on Foo (Foo is written after the compiler), but if Foo could somehow emit its type information during compilation, then the compiler could depend on that.
- can16358p 3y ago
- anonzzzies 3y agoThanks for this. I thought I was screaming into a void. I started with typescript in 2018 and after two years started to believe this is just not really a solution because what it is. I came from Haskell/c#/f#, and TS, while it has a very powerful type system, just doesn’t give you much of the advantages the above languages give you outside (some of) dev. Even when it does, it is really limited in practice (aka when dealing with the real world) vs, let’s say, c#. You can defend from that somewhat, however, you have to always keep the extremely (and that’s intended, but not what it could be) leaky abstractions in mind to not run into bugs that shouldn’t be possible in something that claims static typing (if you don’t know that it drops to js without checks after compile).
- seanmcdirmid 3y agoThe point of TypeScript was always to run on web, it wasn't meant to give you a language advantage over say, C#. You use C# if you have to develop for .NET, you use TypeScript if you have to develop for Web, you wouldn't use one or the other in another context. That being said, TypeScript is differently capable from C#. C# is nominally typed, with decent reified generics. I like programming in C#, and miss its features when programming in TypeScript. TypeScript, on the other hand, is structurally typed, forgoes soundness, and comes with a powerful type system to express complex type relationships (again, possible because it forgoes soundness). I like programming in TypeScript also, and also miss its features when programming in C#. I doubt a language that combined C# and TypeScript would be very nice, these languages go in different directions to good effect, but they are not compatible directions.
- anonzzzies 3y agoBut that’s when you focus on the type system theory and I agree with that. I don’t see how enforcing types after compilation has anything to do with a programming language for the web vs ‘not for the web’ though, but I understand it is the philosophy to check the types and then drop to plain JS. Best tool for the job, sure, but literally losing everything typed you wrote and designed after compilation is just not as useful as it could (should imho) be. You express whatever, it compiles, and then everything can break all that you carefully set up, without any errors. That’s not the language or type system per se, it’s the compiler implementation or rather the philosophy to stay close to js and have a very thin (powerful) layer at compile time only. Typescript in wasm, Deno maybe (didn’t try yet) etc could change this. Then we can have types as in other languages. Not sure why this would not be a win for everyone vs the current status. Also, as you know, the run the web went out the door with nodejs; many backends are now typescript and indeed competing (… for at least writing web apps) with c#.
- LispSporks22 3y agoI've heard the same complaint about Elm
- shadowgovt 3y agoNormally I'd say "hard pass." I'm pretty comfortable with static types being a model where the compiler throws the type information away at compile time, so I can type with abandon without worrying that I'm going to impact runtime performance in my generated code. ... TypeScript may be one exception to my rule of thumb. It's already compiling down to JavaScript, so you're already paying a performance tax in having your code run in an interpreted language. The question should be "how much more of a performance tax are you paying annotating things with type runtime metadata?"
- mrkeen 3y agoWhy not just let the compiler build the deserialiser out of the runtime information during compile time, and then throw out all the types?
- klysm 3y agoSo this is asking for a completely different language?
- benatkin 3y agoPlease give me an integer type. Just kidding, but I'm not pushing for JavaScript anymore. If rust/WASM works as well, I say go with that.
- hajile 3y agoJS added BigInts quite a while ago.
- deleted 3y ago[deleted]
- vbezhenar 3y agoYet JSON.parse("9007199254740993") returns 9007199254740992, not 9007199254740993n.
- orthecreedence 3y ago> Just kidding, but I'm not pushing for JavaScript anymore. If rust/WASM works as well, I say go with that. This is the direction I'm going. I use rust a LOT these days, and after trying out typescript for a few projects over the course of a few months, I absolutely hate it when comparing it to rust or even any other compiled language. Something about it just rubs me the wrong way...maybe the fact that it has to be JS-compatible, so the type system seems really crude? I can't put my finger on it. It sort of hits this weird inbetween where js is quick to write/prototype and rust is extremely "correct" but the ts type system slows things down/annoys me without providing enough benefits. Also, working with it in nested projects via npm tends to be a huge pain in the ass. Maybe I need to switch to Deno or something so it's native? Now that rust/wasm is ramping up, I'm considering using rust for the API layer and something like Leptos for the frontend. I've been getting into svelte a lot, and Leptos seems similar enough to not be a huge leap.
- benatkin 3y agoI'm curious what you think about Dart/Flutter if you've gotten a chance to dig into them. I am very impressed, but it trades simplicity for being cross platform. It has a nice set of types though. https://dart.dev/language/built-in-types https://dart.dev/language/built-in-types It also has a WASM compilation target that is under early development. https://docs.flutter.dev/platform-integration/web/wasm https://docs.flutter.dev/platform-integration/web/wasm
- unilynx 3y agoWhat I really miss is a way to extract type information directly from the compiler. Ie to have a ‘macro’ that takes a type as an input and returns a readable text or a json structure describing that type It still wouldn’t be runtime typing, the compiler would just insert a constant wherever you use such a macro so I don’t think it would conflict with typescript’s goals. But it would make it a lot easier to build extra checks when deserializing data - or just give richer debug information. But it would probably be hard for eg esbuild to support such a feature if tsc adds it. So I couldn’t use it anyway :)
- Tade0 3y agoWe have types at home. My litmus test regarding whether I can even consider using a library in production is: does it have more stars than fartscroll.js? https://github.com/theonion/fartscroll.js/tree/master https://github.com/theonion/fartscroll.js/tree/master Most of the entries there are below that number, which begs the question: is this really that much of a problem that it mandates the drastic changes required? I actually don't know if it's even doable, considering TS's structural type system, where the answer to the question "what type is X?" is not straightforward.
- jmull 3y agoI'm kind of doubting the real value of this. For validation, ORMs, APIs, etc., once you move beyond the simplest cases, you need more information than is present in Typescript type information. And that's before we get to the app-specific concerns. So you're going to end up with schemas, boiler-plate, code-generators, and/or glue code anyway. Not to mention the libraries to help manage this stuff. It's not that it's completely unhelpful, but I think it's a partial solution, and not the tricky part either.
- nycdotnet 3y agoThe TypeScript language service which powers IDEs and which is maintained/shipped with TypeScript already has the knowledge of all the types in your application. It seems like it would be relatively straight-forward (though a lot of work!) to develop some sort of code gen library that uses the TypeScript types known to the language service to reflect on those types and emit some sort of runtime type validation functions as part of a build step. This could be done in an npm module similar to webpack or in an IDE plugin. If that functionality doesn't exist today given all the listed open source projects, I'm kind of surprised. I don't think the TypeScript team would need to do anything to allow such a project to be developed.
- benatkin 3y agoIt has quite an awkward way of being distributed. If you google for standalone TypeScript language services you'll find unofficial ones. Deno's is much simpler. Maybe they should pioneer this. Edit: Actually this is the first result, I hadn't tried those exact terms. It's a bit hairy though, which is why the unofficial typescript-language-server npm package wraps it. https://github.com/microsoft/TypeScript/wiki/Standalone-Server-(tsserver) https://github.com/microsoft/TypeScript/wiki/Standalone-Serv...
- lolinder 3y ago> Type erasure is good! It means JavaScript project can consume TypeScript projects without any knowledge of TypeScript. It's just emitted JavaScript. This does not mean you can't emit the type information separately in a consumable lookup table that's separate from the code. The lack of this type information means we use esoteric libraries which ultimately pollute the JavaScript with all the convoluted typing working arounds... soo... type erasure has defeated the purpose of type erasure. It's a second order effect, where the design goal defeats the design goal. :( I think the author misunderstands the design goals of TypeScript. The goal isn't to have pristine, beautiful JS code with no complexity, the goal is to have the runtime semantics of TypeScript be identical to the runtime semantics of JavaScript. Barring the regretted exception of enums, TypeScript can be converted to JavaScript by simply stripping type annotations. That's the design goal, and that goal is not in conflict with itself. The ecosystem that has built up around TypeScript depends on complete type erasure, and much of it would evaporate if this wish were granted. TS support in ESBuild, Deno, and Bun would become nearly impossible, because each would need to re-implement all of tsc in their respective languages, while right now they just need to maintain their own simplified parsers. On the other hand, the convoluted libraries that OP bemoans are perfectly compatible with all of these tools, because they're implemented in user space.
- shortrounddev2 3y agoThere are plenty of ways to emit runtime type information statically without a runtime. `keyof` could statically convert to the list of keys in a class. Hell, even typescript classes could do what ES6 classes do and initialize class keys to undefined. Currently, typescript classes erase all keys unless explicitly defined. Object.keys() on a newly instantiated typescript class without set members will return nothing, while an ES6 class will return all of the keys. Just an option in tsconfig.json to convert TS classes to ES6 classes (or just allow ES6 classes to exist at the same time in Typescript) would make some code generation WAY easier. Or some kind of syntax to emit the name of a type as a string. Currently, if you run `typeof foo` it will return the type as a string. If you could have a static version of that, like `tstypeof foo`, or with a class: class Foo { bar: string; }; console.log(tstypeof Foo::bar) // or something less C++-looking; compiles to "string". then it would be killer. This could break compatibility if you change the type of a field and a compiled client using the code were to expect "string" when it's been changed to "number". But I'd rather live in that world than the one we live in now Just some basic RTTI would make a lot of ugly codesmelly boilerplate Typescript code evaporate instantly.
- vbezhenar 3y agoThe one downside of this proposal is faster typescript processors like esbuild. Right now they don't care about types, they just strip them from the code. It allows them to be very fast and provide fast feedback loop. With this proposal those tools must become extremely more complicated and probably they will just be as slow as tsc.
- deleted 3y ago[deleted]
- orthecreedence 3y agoReflection on a language that compiles to javascript? I don't get it. Why are people so allergic to macros?? Every stinking language that has compiled to JS has had a chance to do macros but they don't. Coming from many years spent in the lisp world, metaprogramming is this incredible feature that, in my experience, completely negates the need for runtime reflection while adding many other possibilities as well. I get it...the syntax is way harder when your language isn't basically a pre-parsed AST. But rust does it. Seems like a huge waste.
- kazinator 3y agoTypeScript imposes more detailed typing onto JS objects. It makes sense to ask the question: can the type imposed by TS onto a JS object be reified as a run-time object? It could be, but maybe the use cases for that can be solved in another way that don't require the type system at run-time. The good news is that static type is, well, static. All the objects of the same type can share a pointer to the same type metadata. The overhead is thus not necessarily huge: one extra property to initialize when an object is created. The generated TS code has to carry the run-time support routines for the type stuff though.
- vbezhenar 3y agoWhat're you talking about? JS has had macros since the dawn of this world. Just eval(anything). For example eval(tsc("function f(x: number): number { return x + 1}")). Easy!
- tinideiznaimnou 3y agoPreach, brother! If only ECMAScript had a native macro system, TypeScript could be just a library - and I would have zero problems with its existence. You're probably familiar with the following anecdote: >Eich originally joined intending to put Scheme "in the browser",[4] but his Netscape superiors insisted that the language's syntax resemble that of Java. JavaScript became the language that we all love to hate due to political, not technical reasons. Yet people look at me funny when I call out the TS/React monoculture as the blatant corporate power grab that it is.
- 3y ago
- BiteCode_dev 3y agoWhile type hints in Python are not as nice as typescript annotations, I understand their plea, because once thing Python does better is runtime introspection. Which means we can have dataclass, pydantic, typer and fastapi all generating their stuff from regular type hints. No need for special syntax or functions. And that's super nice.
- DanRosenwasser 3y agoHey all, TypeScript PM here. I understand the desire here. Runtime type checking is often necessary for data validation, and we can see lots of libraries developed to help fill the gap here. But I think the fact that there are so many libraries with different design decisions is pretty indicative that this is not a solved problem with an obvious solution. We knew this going into the early design of TypeScript, and it's a principle that's held up very well. What have been happy to find is that we've grown TypeScript to be powerful enough to communicate precisely what runtime type-checking libraries are actually doing, so that we can derive the types directly. The dual of this is that people have the tools they need to build up runtime type validation logic out of types by using our APIs. That feels like a reasonable level of flexibility.
- scotty79 3y agoMaybe official preprocessor plugins for TypeScript compiler could help? I understand that everybody who needs it can already put their own preprocessor that generates runtime objects from type information before the code is passed to tsc for compilation. But the effort is inconsistent and distributed. If TypeScript officially supported pluggable preprocessor and plugin ecosystem for it some good solutions might get discovered.
- andix 3y agoWhat's next? An official TypeScript UI framework, will it be Vue, React, Next.js or Svelte? An official TypeScript date library?