I don't think Godot's cli is exactly the same thing as this. Godot's cli allows you to start Godot, do some command, and exit. This allows you to do operations on a running instance of Unity and get structured text output back. It's explicitly made with LLMs in mind.
They're both cli's and Godot was there first, but this isn't really an apples to apples comparison.
I know Jerry Map (I hope that someday will be a exposition in Spain) because I love it, I love the https://en.wikipedia.org/wiki/Outsider_art. The people who maybe mad and they built a world with own rules.
It's a weird coincidence to me I just remembered Henry Darger again today, within the last hour actually. I had watched "In the Realms of the Unreal" (2004 documentary) in the theater when it came out. (I know it's only a coincidence because it's something I'm interested in thinking about, but it feels meaningful anyway.)
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).
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.
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.
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
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.
reply