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

Okay, now it is official, JS/TS becomes a C# clone ;)

no surprise considering the TS people



That was my first though, but a) it seems that the `using` syntax is not exactly the same as in C# (unless the old C# I used to use) and b) still I wouldn't mind, C# is a great language


And this is a good thing. I would love to see something like a proper C# instead of a hacky TypeScript. It would be so much more productive.

JavaScript is a cool dynamically-typed language though. C# is on another side of the spectrum: it is super cool by being fully strongly-typed. But TypeScript is something in the middle and this uncertainty gives pains.


I find that Dart rides that middle line much nicer than typescript does, at least for now. As of Dart 3, you can now have sound null safety, and sound type safety for 100% of your code, if you want. The recent addition of records also makes working with some of javascripts methods with multiple return types better, as that is one of the things dart is still missing, union types. Though, I tend to prefer dart over typescript just because of not having to deal with the node ecosystem at all.


Do you use Dart for anything other than Flutter though? I'm a huge fan of Dart, but I don't see it getting much server usage. Like, could I deploy a Dart CloudFlare worker?


yes, cloud flare even has a guide on their docs if you go to the Workers > Platform > Languages section. Also, dart 3 is previewing wasm support, and could be used through a wasm worker.


Too bad Dart is only used in Flutter.


That’s your choice, I suppose. I use it for everything from flutter to CLI to Cloud Functions to WebUi to daemons in tiny containers.


> That’s your choice, I suppose.

Not really.

For personal projects or if you're a freelancer sure. Once you work in a company/startup you can't go and implement things in whatever you like.

It's way easier to convince any manager that Dart/Flutter is a good choice for a mobile app because of the tech advantages than in anything else because of the pool of available developers.


Man, the context of question, is how to use Dart in a Typescript/React application (because of popularity of ReactJS ecosystem, of course).


Any way to use Dart with React in a .jsx way? It looks like Dart has exclusive support for Flutter, and that's it.


Honestly typescript is fine, just give me:

Standard library that isn't worthless - no more npm package spam.

Type knowledge in the runtime. It doesn't have to be typed, just make it so I don't have to do crazy checks on properties before casting to a class.

Imports without webpack.


> "just make it so I don't have to do crazy checks on properties before casting to a class."

You do have 'instanceof' at runtime, so unless you mean some other type of 'class', casting to a class is really a non-issue (and you don't really 'cast'... since dynamic typing and all). If you mean some more advanced concept (e.g., structural type runtime checking), think how you would do it in statically typed languages (is it really better?).


Instance of doesn't work sometimes and you have to write explicit property checks. I forget the details because I'm by no means a typescript expert, but I remember being very frustrated by the fact I couldn't just use instance of.


It doesn't work when objects cross global scope boundary (e.g. you get an object from a frame), there's no fixing that, by design the namespaces are different and unrelated.


instanceof only works with JavaScript classes. Not on regular objects that just structurally conform to a type or interface.


Classes aren't the only way to define types?


JavaScript has half decent object construction syntax that avoids the nesting hell of classes:

    function Foo(s) {
        this.s = s
    }

    Foo.prototype.bar = function() {
        console.log(this.s)
    }

    const baz = new Foo("Baz")
    baz.bar()
But it seems Typescript can't handle it?


Well there are 2 issues:

(1) imperative style mutation of the prototype is runtime dependent, and typescript can't really rely on runtime behavior.

(2) Foo has two incompatible types in JS, it is both `(s) => void` and `new (s) => Foo`, typescript by default will assume the first signature (which is usually what people want).

In any case, you can specify the types (though in 99% of the cases, just use a class):

   interface Foo {
       s: string;
       bar(): void;
   }

   const Foo = function(this: Foo, s: string) {
       this.s = s;
   } as {
     new (s: string): Foo;
     (this: Foo, s: string): void;
   };
   
   Foo.prototype.bar = function(this: Foo) {
       console.log(this.s);
   }
   
   const baz = new Foo('Hello');
   baz.bar()


> though in 99% of the cases, just use a class

While that is a fair statement, I've been reading a lot of Typescript code lately and it seems in 99% of cases the selected solution is to use top level functions and globals to avoid the nesting hell class introduces, albeit introducing the global hell in the process. In practice, 'just use a class' doesn't overcome the human element.

Javascript was on the right track originally, but then veered off into the weeds for some reason. I appreciate you pointing out how it can be done. Although the solution is very much second class citizen, sadly. This certainly isn't going to wean developers away from global hell. Hopefully Javascript/Typescript can make some strides in improving this going forward.


I'm not sure what improvments are you suggesting.

We are talking about runtime class creation with dynamic methods, while still adding proper static types. There aren't many language allow this level of flexibility.

You can probably disallow prototype use with existing tools if that's desired, but it is an advanced tool for advanced use cases (which still exist).


We are talking about how poor syntax pushes developers into some strange corners to avoid having to deal with the poor syntax. class ultimately gets you to a decent place, but forces the code into one big giant mess that nobody wants to look at ever again. Prototype function assignment gets you to the same place, with better syntax, but falls short for other reasons.

Given:

    class Foo {
        constructor(x) {
            this.x = x
        }

        bar() {
            return this.x
        }
    }
maybe it becomes:

    object Foo(x) {
        this.x = x
    }

    function Foo.bar() {
        return this.x
    }


Structural typing is a thing.. also there aren't really classes in js in the Java sense, it's all prototype chains.


instanceof only works for inherited types, usually expressed with the class keyword by TypeScript users. It's entirely worthless if you're not using them. Class is the only construct in TS that is both a type and a value.


> Standard library that isn't worthless

This is exactly what bugs me about TypeScript. The language itself is fine—some annoying things, but generally they’re due to having to run on top of JS. But Microsoft had the chance to fix JS’s terrible standard library. And they didn’t!


Give io-ts a try for the runtime type checking. We’ve used it in prod for a few years now and it’s pretty solid.


What's missing in the standard library though? I hear this complain often, but when I use a library it's always for a specific use case and not something that I would expect to be in a standard library.


> Imports without webpack.

https://caniuse.com/?search=import


Imports through the browser do, but I'm wanting a single file bundle with all those imports so I'm not relying on a browser feature to deliver the content over N requests.

I know that's less of a concern nowadays with modern http, but guess who still supports ie11


I'm sorry you are stuck still supporting IE11. You could use an AMD loader and use imports in Typescript configured to transpile AMD modules. Most AMD loaders were tiny. The benefit to AMD modules in your case is that they don't need webpack to bundle, the (hideous) module format was designed to be bundled by raw concatenation and the Typescript compiler will still even do that for you with the --outFile parameter (or "outFile" tsconfig.json setting).

It feels like terrible advice to give someone, given ESM is far superior to AMD, and this would be going backwards in time, but in your case you are already blighted by the disease and it is advice that might staunch some of the bleeding.


But that is the niche of TypeScript. It supports a dynamic typed language by enabling some but not all benefits of typed languages.


Nominal types versus structural types is basically the main distinction at this point (if we ignore .net, etc). I like both languages, happy to see them converge while keeping their defining characteristics


Where do C# anonymous types fall? From a functional perspective, they are a purely structural type.

Here's a snippet of C# I wrote recently to transform some JSON:

    var transformed = media.Select(m => {
      var parts = m.Split('/');
    
      return new {
        addedAtUtc = "2023-05-15T05:59:31.398Z",
        originTripUid = parts[4],
        path = $"{parts[4]}/{parts[5]}",
        rank = "",
        size = 103978,
        stored = true,
        type = "document",
      };
    })

    File.WriteAllText(
      Path.Combine(Environment.CurrentDirectory, "output.json"),
      System.Text.Json.JsonSerializer.Serialize(transformed)
    );
It would be easy to mistake this as JS at a quick glance.


They aren't structural because the following doesn't work in C#, but would work (with tweaks to make it valid code) in a structurally typed language such as TypeScript:

  var transformed = media.Select(m => {
        var parts = m.Split('/');
    
        return new {
    addedAtUtc = "2023-05-15T05:59:31.398Z",
    originTripUid = parts[4],
    path = $"{parts[4]}/{parts[5]}",
    rank = "",
    size = 103978,
    stored = true,
    type = "document",
     };
  }).ToList();
  
  transformed.AddRange(otherMedia.Select(m => {
        var parts = m.Split('/');
    
        return new {
    addedAtUtc = "2023-05-15T05:59:31.398Z",
    originTripUid = parts[4],
    path = $"{parts[4]}/{parts[5]}",
    rank = "",
    size = 103978,
    stored = true,
    type = "document",
    documentType = parts[6]
     };
  }));
Adding "documentType" breaks in C# but would work in a structurally typed language as a structural type checker can see that the second result fulfills all of the necessary properties. Doing this in C# would require creating an interface and being explicit.


Unless you were using the (yet unimplemented) exact types in TS. https://github.com/Microsoft/TypeScript/issues/12936


Sure, but that would be opt-in if it were ever implemented. I think both styles of type system have their pros and cons. I have loved the cross-pollination between C# and TS with great ideas flowing in both directions.


Anonymous types are nominal types (like all others in .NET). They are just auto-generated and auto-named.

Duck Typing at runtime is possible and to a degree checkable and compile-time.


I get that; that's why I qualified it as a "functional perspective" because even though the underlying implementation is an auto-generated, auto-named type, the functional usage of it is a structural type (with limitations).


Runtime type systems: TS has none; C# has extensive RTTI

Function dispatch: TS is purely dynamic; C# has both static and dynamic

OOP: Mandatory in C#, optional in TS

Variance: Implicit in TS, explicit in C#

Numeric types: TS has one (number); C# has the entire signed/unsigned/float x 8/16/32/64-bit matrix

There's really no intentional effort to converge them.


TS has two. number and bigint[0], corresponding to Number and BigInt in JS, respecitvely

[0]: https://www.typescriptlang.org/docs/handbook/2/everyday-type...


Your list of differences is correct but not really what I meant. The points you listed are mostly due to JS runtime constraints. The choice of nominative vs structural type system is purely a design choice by the typescript team.


it's really not a c# clone. If anything JS is still more similar to python that it is to c#.

JS already has 'with', so 'using' seems like to closest semi-standard keyword to use.


Of course this does not change the fact that it is a reserved keyword, but "with" is prohibited in strict mode and as such also in any ES Module. I assume this also applies to any TS module regardless of the compiler.

But since TS is supposed to be a superset of JS, of course this does not change anything


when you substract everything what C/C++/Java is, this will be interesting comparison what is closer ;)


but using keyword will be in js eventually as it is in stage 3 now


wasn't that the goal from the start




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

Search: