Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I'm misunderstanding your reasoning here. TS is already a new (superset) language which compiles to JS. Runtime types solve the problem of maintaining two duplicate, separate type systems -- one for compilation, one for validating data. I'm not seeing how that's related to OOP. For instance, my preferred workaround lib for this problem, `io-ts`, leans hard on functional programming.


Yeah but just because types exist at compile time doesn't mean they exist at run time.

For instance with Generics in Java a List<String> is the same as a List<Integer> at run time, the compiler can enforce rules that let you add a String to one but not add a String to the other but the runtime has no idea. This has various negative consequences but it also let them retrofit generic collections on top of the old collection implementation in Java unlike the disaster in .NET where both had to coexist for years.

Similarly C compiles to machine code and in machine code there are just memory locations and registers, types are implicit in how you use those things but not spelled out explicitly. C++ does have RTTI but is one of the many open pits, like Exceptions, in C++.

Typescript types are the same way, once the compiler has done its type checking you know the code is going to behave according to the type system even if the types have been "erased".


Java's generic type information (aka parameterized types) is available at runtime through reflection.


Depends on the situation. If you just make an ArrayList<X> (for some specific class X) you can call getClass() on that object and see it is an ArrayList but you cannot find out about the X.

If you make an ArrayListX that is not generic but extends ArrayList<X> it is possible to see the type parameter that was extended, the same is true for implementations.

There are other kinds of type unerasure that you can use w/o the language supporting it explictly, such as you could pass the type parameter X.class into the constructor and put it in a field so that you could call some method like getContainedClass() and get a copy of X.

Now the introspection/reflection API does have support for talking about parameterized generic types that doesn't mean that information always exists at runtime.

I worked on a crazy project where I did a lot of fighting with ordinary types and parameterized types and unerasing types by rewriting the names of methods to avoid conflicts, if you have methods like

   A doSomethingTo(B)
   A doSomethingTo(C)
you can rewrite these to

   Expression<A> doSomethingToB(Expression<B>)
   Expression<A> doSomethingToC(Expression<C>)
but you can't have an overload that takes two differently parameterized expressions, this lets you write Java code in a lisp-like syntax that can be metaprogrammed on:

https://github.com/paulhoule/ferocity/blob/main/ferocity-std...

that project got me thinking a lot about the various ways types manifest in Java and I made the discovery that when you add Expression types you practically discover an extended type systems where there are many things that are implied by the existence of ordinary Java types.


I know how it works. The point of the topic was to have type information available, so we can use it for things like dynamic binding. No one asks for the runtime to be as strict as the type system (the compiler).

I like Venkat's presentations: https://www.youtube.com/watch?v=34oiEq9nD0M

BTW. I do not agree with the opinion in the topic. Since Typescript is compiled to something else (usually JS), I'd prefer Typescript to have proper annotations (there are "decorators") and compiler hooks and just use code generation for concerns like (de)serialization.


Emitting types would run counter to several of TypeScript's Design Goals [0]. In particular, it would violate:

> 3. Impose no runtime overhead on emitted programs.

> 9. Use a consistent, fully erasable, structural type system.

It's also explicitly called out as a non-goal in that doc:

> 5. Add or rely on run-time type information in programs, or emit different code based on the results of the type system. Instead, encourage programming patterns that do not require run-time metadata.

> 6. Provide additional runtime functionality or libraries. Instead, use TypeScript to describe existing libraries.

[0] https://github.com/Microsoft/TypeScript/wiki/TypeScript-Desi...


Emitting type information to some kind of separate common format wouldn't undermine most of these goals. There are already apparently dozens of tools that people can use for this task in a dozen different ways. Just have TS emit the data.

In this way there is no runtime overhead (point #3) -- it's pure data to be optionally consumed. They wouldn't have to prescribe any particular reflection module (point #6).

The only point this would violate is #5 but that is, of course, the point. We want them to reconsider because it's such a powerfully useful feature. And people are doing it on top of and outside of TypeScript where TypeScript would be best tool to give this information for TS users.


TypeScript dev lead here.

Today, you can already write a program using the TypeScript API to inspect all of this information to accomplish whichever scenario is at hand. The existence of all these tools, each with different opinions on design direction and implementation trade-offs, demonstrate that this is possible. Yet it's not demonstrated how those tools would benefit from reading from a data file as opposed to using the TypeScript API.

Something like api-extractor has different constraints from io-ts which has different constraints from typescript-schema. The API exists today and is apparently sufficient to meet all these tools' needs, yet what's proposed is a data file that can encapsulate any possible operation you might perform with that API.

Having TypeScript try to imagine, implement, and maintain a data file format that can satisfy _all_ of these tools' use cases, plus any future tool's use case, is a tremendous effort with no clear upside over using the existing API.

It's easy to gain support for the idea of "put the types in a file" because anyone reading that can imagine a straightforward implementation that just achieves their particular goals, but everyone's goals are different and the amount of overlap is not actually all that high when you look at the wide breadth of tools in the list. There's a very different amount of information you'd need to enable a type-aware linter (which is basically type info on every expression in the program!), as compared to a simple documentation generator (which might only need top-level declaration info).


Hard to argue with that! I wonder why this isn't considered a solution to the author of this site.


The author explicitly calls out the existence of all of these tools as being the problem. They seem to want a canonical version that TypeScript itself officially supports.


Situation: There are 14 competing type representation formats

TypeScript: We can write our own type file format!

Situation: There are 15 competing type representation formats


If typescript itself defines a format, it's hard to imagine that the majority of people won't switch to it.

Though while there's a lot of type-data tools, are there actually a lot of type-data formats out there right now? I've been using zod, and it doesn't have one. You have to use code to tell it about a type. Someone did make a library to let zod load types from pure data, but the format used there is... typescript source code.


It would violate #9 no matter what implementation you use, and #9 is absolutely essential to tools like ESBuild, Deno, and Bun, which all rely on the assumption that they can nearly instantly strip out the type annotations and execute the code as JS.


You'd still be able to execute the code as JS. Your library that uses type reflection wouldn't work anymore but that's true of all these solutions.


No, it's not. I can take a library that uses zod, strip the annotations, and it will execute perfectly anywhere I want to run it.


That's because Zod doesn't use type annotations as input. We're talking about wanting to use type annotations as input so that we don't have to make our code as ugly as Zod makes it.


If some design goals are stupid they must be changed. It's not god word. It's human word. And this human was wrong.


This isn't just some of the design goals, type erasure is the fundamental guiding principle of TypeScript that allowed it to become successful. Throwing it away because it complicates certain programming patterns should not be done lightly.


In my opinion they are not stupid, they make a lot of sense. And many people seem to agree and use typescript. If you don’t agree, use something else. There are many alternatives, pick something that is „smart“ in your opinion.


Unfortunately i can't. Like most of the people here i work in a company, with other people and i can't chose $language that is less dumb for obvious reasons. Typescript IS the only practical solution for web development at scale. I'm stuck with the design philosophy of a guy that's not facing my problems and obviously doesn't care.


Small ot, if you like io-ts, @effect/schema is the spiritual successor from the same ecosystem.

The fp-ts, io-ts author Giulio Canti has decided that the best way to proceed was to merge the two communities of fp-ts and effect, even though it's his work that is mostly known with effect being much more niche.

It's essentially io-ts squared in its powers. The amount of things you get from schemas are endless, not just decoders and encoders but also apis, lenses, constructors, and many other things.

It's obviously heavily fp-leaning, albeit I would say effect systems such as effect, based on Scala's ZIO, are much more approachable than haskell/purescript-like languages.


> TS is already a new (superset) language which compiles to JS.

Yes, but also no. The point is that it doesn't really add more semantics over plain JS. You can erase all the type annotations (well, replace with "any") and it'll do the same thing if you ignore the type checking.

If there's any "transformation" from TS to different-looking JS[0], it's mostly just syntactic embellishment (think LISP macros and such), not semantic.

[0] Not sure if there is, tbh




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: