4 ms·
Formatting is rudimentary but it exists: https://news.ycombinator.com/formatdoc https://news.ycombinator.com/formatdoc Your example is actually a really good o
by jolux 6y ago
Formatting is rudimentary but it exists: https://news.ycombinator.com/formatdoc https://news.ycombinator.com/formatdoc
Your example is actually a really good one for discussing these differences, and the syntax is indeed similar. That TypeScript code is introducing a "type alias," which is a special name for another type, rather than a new type of itself. (https://www.typescriptlang.org/docs/handbook/advanced-types.html#type-aliases https://www.typescriptlang.org/docs/handbook/advanced-types....)
This is a concept that F# does not have, because F# doesn't support structural typing. In TypeScript, you could just as well specify that a function returns
{
amount: number;
account: number;
}
directly, and it would be equally compatible with anything expecting a "Check," because Check is just a shorthand for that object type. I can't easily declare that a function accepts { account: int; amount: int; } in F#, I have to declare that it accepts "Check." That is the main difference between TS and F# here, and incidentally also the most basic difference between structural and nominal type systems.
I'm not sure why the syntax is similar though, F#'s is based on OCaml's record syntax while TypeScript's is really just a JavaScript object literal but with semicolons instead of commas. I believe it supports commas too. It may be genuine coincidence, or the designers of TS may know of the ML family, which is highly influential among language designers and implementers.
- bern4444 6y agoThanks for the formatting link, exactly what I was looking for to format code a bit better. That actually helps me understand some F# code I wrote last weekend as well regarding construction of objects of a certain type... I didn't know about the difference between nominal vs structural types but your explanataion makes sense. It's the subtle distinction between a type vs a type alias that you pointed out. I personally use type aliases in typescript over interfaces, I think they're a more natural fit for JS than interfaces but that's a separate conversation :) Language design is really interesting especially the choices designers make. I feel like they must all pull at least in part from each other and would be curious to explore any relationships but if its total coincidence that's pretty incredible too.
- jolux 6y ago> I personally use type aliases in typescript over interfaces, I think they're a more natural fit for JS than interfaces but that's a separate conversation :) The TypeScript docs recommend the opposite, preferring interfaces. Interfaces are also structurally typed in TypeScript though; the major differences are that interfaces can only be used to declare object types: https://microsoft.github.io/TypeScript-New-Handbook/everything/#interface-vs-alias https://microsoft.github.io/TypeScript-New-Handbook/everythi...
- bern4444 6y agoI don't see that recommendation on the page... The fact that interfaces are limited to typing objects but type aliases can also be used for functions is an easy +1 to type aliases. My view is that declaration merging is a bit of an anti pattern that could cause trouble if two different people write an interface with the same name but to represent different data... now they get merged incorrectly. A type alias forces more explicit behavior where composition must be done by creating a new type alias as the union of two or more other types type Foo = Bar & Baz Edit: found the page, its here https://www.typescriptlang.org/docs/handbook/advanced-types.html#interfaces-vs-type-aliases https://www.typescriptlang.org/docs/handbook/advanced-types.... Yeah, not sure I agree yet but I could be persuaded... I don't think type aliases prevent extension, they just force it to be explicitly declared.
- jolux 6y agoI think it’s a +1 to using both depending on where they fit. I use type aliases for defining unions and intersections and such and interfaces for everything else, personally. And that’s an intersection you’re describing there, not a union. Interfaces are explicit about extension as well, they use the “extends” keyword.
- bern4444 6y agoWhoops, yes that is indeed a union not an intersection. Thanks for the correction. I'm still getting used to the terminology. The explicitness I was referencing is around the declaration merging. Its automatic so unless there's a conflict between two interfaces with the same name but with different properties, a dev wouldn't know that it was being done. I agree with using what makes sense for the scenario. I prefer type aliases for functions and interfaces for classes and that seems to work out pretty well so far.
- Smaug123 6y agoYou can do anonymous records in F# - you don't have to explicitly give a name to your record types - but structural typing solves similar problems to those solved by interfaces, and F# thoroughly supports interfaces, so I imagine it wasn't thought necessary to make the type system any more structural.
- UK-Al05 6y agoAnonymous record?
- jolux 6y agoDoesn't support structural subtyping either
- UK-Al05 6y agoF# does have type alias. It takes the form type newname = oldname You can do things like type LoadReceipt = RecordId -> Record let sqlLoad: LoadReceipt = implementation let noSqlLoad: LoadReceipt = implementation You can use it like an interface, and accept loadReceipt functions for anyone who needs to load receipts... Then partially apply a SQL version, noSQL version etc. I use this in my code.
- jolux 6y agoI know, but in TypeScript the compatibility is structural.