Hacker Newsnew | past | comments | ask | show | jobs | submit | mdtrooper's commentslogin

What has always bothered me about TypeScript are union types. If you have a function that receives a parameter such as ‘Dog | Cat’, you cannot separate it. For example:

type Dog = { bark: () => void }

type Cat = { meow: () => void }

function speak(animal: Dog | Cat) {

    if (‘bark’ in animal) {

        animal.bark();

    } else {
        animal.meow();
    }
}

Okay, okay, I know you can filter using ‘in’ to see if it has methods, but in real life, in a company where you have a colleague (who is a golden boy) who writes over-engineered code with hundreds of interfaces of interfaces, you don’t want to spend time searching through the files to find every element that is in the union type.

Whereas in Rust it does:

struct Dog { name: String, }

struct Cat { name: String, }

enum Animal {

    Dog(Dog),

    Cat(Cat),
}

fn process_animal(animal: Animal) {

    match animal {

        Animal::Dog(dog) => {

            println!(‘It is a dog named {}’, dog.name);

        }

        Animal::Cat(cat) => {

            println!(‘It is a cat named {}’, cat.name);

        }
    }
}

I think TypeScript should add a couple of lines of code to the generated JavaScript to do something like:

type Dog = { bark: () => void }

type Cat = { meow: () => void }

function speak(animal: Dog | Cat) {

    if (animal is Dog) {

        animal.bark();

    } else {

        animal.meow();

    }
}

The idiomatic way to do this in TypeScript is with discriminated unions. You’re basically just giving the type system an extra property that makes it trivial to infer a type guard (while also making the runtime check in the compiled JavaScript foolproof).

This does act exactly as a discriminated union. The code works exactly as written.

You're looking for a discriminated union [1], which idiomatically:

  type Dog = { bark(): void; type: 'dog' }

  type Cat = { meow(): void; type: 'cat' }

  function speak(animal: Dog | Cat) {
    if (animal.type === 'dog') {
      animal.bark()
    } else {
      animal.meow()
    }
  }
Generally speaking, TypeScript does not add runtime features.

TypeScript checks your use of JavaScript runtime features.

[1] https://www.convex.dev/typescript/advanced/type-operators-ma...


Your first code block works exactly as you would expect and has been working like that for many years

https://www.typescriptlang.org/play/?#code/C4TwDgpgBAIg9gcyg...


The op did say they didn't want to do these type of checks.

I thought the answer was 'instanceof'?

https://www.typescriptlang.org/docs/handbook/2/narrowing.htm...


I see what you mean, thanks. instanceof works if you're using javascript classes but not for "types".

You can't do `instanceof Dog`. `instanceof` is a JavaScript feature

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...


Typeguard is what you are looking for: function isDog(animal: Dog | Cat): animal is Dog { return "bark" in Dog }

Then: isDog(animal) ? animal.bark() : animal.meow() You get full type narrowing inside conditionals using typeguards.


You don't even need that. The code exactly as presented acts as a discriminator. TypeScript is smart enough to handle that logic in the if block and know whether animal has been validated as Dog vs Cat. GP is complaining about a feature that already exists in TypeScript

I’m not at my computer so I can’t remember the exact behavior of this situation, but was OP more so referring to autocomplete abilities of typescript? I think they were saying, you first must know if the object barks or meows, you must first type that in in order to get the benefit of type checking and subsequent autocomplete conditional body, which is annoying when you are dealing with complicated types. It requires you to do some hunting in to the types, rather than using a piece of code more like an interface.

It depends how you construct Dog and Cat. With Javascripts dynamic prototype chain, you could never know for sure.


type Mutt = Dog & Cat

const imposter: Mutt = { bark: () => console.log("woof"), meow: () => console.log("meow"), }

You're both misunderstanding parent's point as well as the original point. Nobody ever claimed your link wouldn't compile.


I see what you mean, thanks

Well imo GP is fundamentally misunderstanding TypeScript. It's explicitly a structural language not a nominal one. It goes against the entire design philosophy of TS


It would have been a super reasonable reply to talk about the history of TypeScript, why fundamentally its types exist to retroactively describe complicated datastructures encountered in real world JavaScript. And why when TypeScript overstepped that by creating enums, which require code generation and not mere type erasure to compile, it was decided to be a mistake that they won't repeat.

But instead your rebuttal was pointing out that TypeScript can compile OP's example code, which OP presented as valid TypeScript that they disliked. I'm not defending their position, I'm just saying that it didn't appear you had even properly read their comment.


You're talking about adding a runtime feature. TypeScript doesn't do that anymore. It can't control what properties are on objects or add new ones - you do that yourself in the standard JavaScript portion of the language. TypeScript only lets you describe what's there.

As a sibling said, discriminated unions are they way to go here. You can also add custom type guard functions if you can't control the objects but you want to centralize the detection of the types, but it's better to let TypeScript do it itself so that you don't mess something up with a cast.


And then you have a

    const CatDog = { bark(){}, meow(){} }
and

    const TreeCat = { bark: "oak", meow(){} }
and your code stops working

To make types discriminatable you need either

    type A = { bark: fn, meow?: never } | { bark?: never, meow: fn }
    type B = { species: "dog", bark: fn } | { species: "cat", meow: fn }
    or use instanceof with a class

That's intentional, TS types are erased in runtime. My go-to way for this is discriminated unions: https://www.typescriptlang.org/docs/handbook/unions-and-inte...

What always bothers me with enums, sealed-types, etc is that I can't compose a new ad-hoc set based on elements of someone else's enum. You can make one using the other but not the other way around, TypeScript's is more general.

You can literally do what your generated example does using a type guard. You can also use method overloaded signatures if you dont want to expose your API consumers to union types.

You need a tagged union for this in typescript.

this post on union types versus sum types is worth a read (the tl;dr is that they both have their uses and one is not strictly better) https://viralinstruction.com/posts/uniontypes/


Some years ago a chinese company released a phone with 2 screens, one typical mobile screen and other side a e-paper screen. But I don't remember what happened, but unfortunately this idea didn't succeed.

There are also Hisense phones, I had one for a while but having to live with stock firmware severely limited its longevity.

YotaPhone. I really wanted to try that but it was way too expensive for a gimmick

Russians had that like a decade ago. It’s dead.

There is not a old socket from the toilets in the old trains (maybe trains are 60 years old...more or less 1970) in Spain. This sockets are near the mirror and I think that this sockets were for old electic shavers.

is there a download or play online?


I remember that years ago when the android phones started there was a app for flash games....I don't remember the name the app (and maybe this app does not run in current android phones)

Now thanks to https://f-droid.org/es/packages/rs.ruffle/ (it has high % compatibility but it is ok) another we have again a handful flash games in the phone.


There was a browser-streaming app that would play them remotely, can't remember what it was called.

There was an official plugin by Adobe on Android but it was awful, I remember watching them showcase it at a conference it was tragic even with their handpicked and simple example.

Then there was a transpiler that produced native apps from Flash, this was actually pretty good but Apple then banned transpiling which killed its viability entirely, six months later they un-banned transpiling but the damage was done.

But on the plus side, Apple got to monopolize transaction fees in Flash games like Farmville for nearly two decades!


It's sad, but in the battle for a free ecosystem in video games, we must all join forces towards a single goal. IMHO, it's Godot.


the real free ecosystem is your programming language of choice, audio and graphics drives with I/O from the system


I know similar web about paper airplanes (maybe I found in HN too some years ago):

https://www.foldnfly.com


There is another adventure framework as plugin for Godot. It is Escoria: https://godotengine.org/asset-library/asset?user=escoria

https://docs.escoria-framework.org/en/devel/


There's also 'Popochiu': https://github.com/carenalgas/popochiu Both seem to be in maintenance mode though and are not as battle tested as AGS.

The problem with these engines is you need to become familiar with both Godot as well as the point&click extension making them less suited as a first adventure authoring platform.


I think these kind of things will bring problems.

Because Nint€ndo or $ony (and others game companies) have a big problem, their old games are awesome and if the people can play these games, then the people will be happy and will not need new games or new sagas.

Because the problem is not the people playing old games, the real problem is the people will not pay for new games

And we know that these companies have army of lawyers (and "envelopes" to distribute among politicians) to change the laws and make illegal something that is not illegal.


I have very little sympathy for these companies. They make access to these titles difficult if not impossible. Preservation matters and they have no interest in anything but the bottom line today.


It’s interesting, because they could potentially make millions, if not billions by selling access to them as a subscription.


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

Search: