I’d love to see a deeper cut: Is there type inference? Destructuring? Product and sum types? Can we see examples of the same thing using both tools? How about examples of things one can do that the other can’t?

I’d also love to see stronger opinions: Should I decide just on the basis of existing Angular/React? If I don’t use either, which tool should I pick? Does one have a noticeably larger, friendlier community?

Should I decide just on the basis of existing Angular/React?

Maybe in the case of Angular, since it’s really a TypeScript-first framework. React is less opinionated, and TypeScript has really good support for React, including compiling JSX if desired.

If I don’t use either, which tool should I pick?

TypeScript is a fair bit older and more mature as far as I can tell.

Does one have a noticeably larger, friendlier community?

The really big advantage that TypeScript has is the existing ecosystem of third party type definitions which you can install via npm.

Say you want to use LoDash, which isn’t written in TypeScript, but you want to have your usage type checked. Just npm install @types/lodash and you’ll get a community-maintained type definition which the TypeScript compiler will recognize, and automatically match up with the existing lodash JS package in your node_modules.

If I understand correctly, what TypeScript has is union types (as in set-theoretic unions), not sum types. The difference shows up when you try to union/sum a type with itself:

-- Haskell
data Sum = A Foo | B Foo

Ignoring bottom, Sum is the disjoint union of two copies of Foo.

Product types as covered by Wikipedia. tl,dr; Haskell/ML/Rust shit.

I suspect we probably recognize them by another name and concrete example, and I also suspect somebody here might be able to bridge the theory with the practice. (nudge nudge @pushcx)

As I understand it, product types are different from intersection types in that product types vary depending on the order of the operands of the product, i.e. “A + B” (where + is the ‘product type operator’) differs from “B + A”.

A struct in C is a classic example of a product type; if you include two sub-structs of the same type (A + A), the elements of each differ, whereas in intersection types A & A would be the same as just A itself, and A & B = B & A.

(I think. Correct me if I’m wrong, someone more knowledgeable; this is based on my interactions with product/sum types in ML-y things, and only a little bit of interaction with intersection types while helping a friend debug some TypeScript, but I have no real-world experience with the latter.)

There is so much confusion in this subthread that I feel compelled to correct some of it:

Sums (⊕), tensor products (⊗), direct products (×), unions (|) and intersections (&) are all different from each other.

Sums, tensor products and direct products are associative and commutative up to natural isomorphism. That is, (A ⊕ B) ⊕ C and A ⊕ (B ⊕ C) are naturally isomorphic, A ⊕ B and B ⊕ A are naturally isomorphic, etc. None of them is idempotent.

Unions and intersections are associative, commutative and idempotent up to strict equality. That is, (A | B) | C and A | (B | C) are the same type, A | B and B | A are the same type, A | A and A are the same type, etc.

Tensor products distribute over sums, up to natural isomorphism. That is A ⊗ (B ⊕ C) and (A ⊗ B) ⊕ (A ⊗ C) are naturally isomorphic.

Unions and intersections distribute over each other, strictly. That is, A & (B | C) and (A | B) & (A | C) are the same type, etc.

Sums, tensor products and direct products play nicely with data abstraction, because they respect isomorphisms of types. That is, if A and B are isomorphic, and so are C and D, then so are A ⊕ C and B ⊕ D, etc. Category theorists call this “not being evil”.

Unions and intersections are “evil” in the above sense, and thus don’t play nicely with data abstraction. Conceptually, unions and intersections require the existence of a single universe of all values, of which every type is a subset. Sounds familiar? Yes, this makes unions and intersections natural candidates for bolting on top of dynamically typed object systems. And, voilà, Typed Racket, Ceylon (yes, the JVM’s object system is dynamic), TypeScript and Flow all have union and intersection types.

Relevant to my current work, thanks!

I’d love to see a deeper cut: Is there type inference? Destructuring? Product and sum types? Can we see examples of the same thing using both tools? How about examples of things one can do that the other can’t?

I’d also love to see stronger opinions: Should I decide just on the basis of existing Angular/React? If I don’t use either, which tool should I pick? Does one have a noticeably larger, friendlier community?

+1, this article left me eager for more.

I’ve been working a lot with TypeScript for the past year, so I can answer some of those.

Yes. Both Flow and TypeScript do type inference.

TypeScript does destructuring. Flow doesn’t, since it’s just a type checker, not a compiler. But you’d usually pair Flow with Babel.

TypeScript has sum types. I’m not familiar with product types.

Maybe in the case of Angular, since it’s really a TypeScript-first framework. React is less opinionated, and TypeScript has really good support for React, including compiling JSX if desired.

TypeScript is a fair bit older and more mature as far as I can tell.

TypeScript is much larger.

The really big advantage that TypeScript has is the existing ecosystem of third party type definitions which you can install via npm.

Say you want to use LoDash, which isn’t written in TypeScript, but you want to have your usage type checked. Just

`npm install @types/lodash`

and you’ll get a community-maintained type definition which the TypeScript compiler will recognize, and automatically match up with the existing lodash JS package in your`node_modules`

.If I understand correctly, what TypeScript has is union types (as in set-theoretic unions), not sum types. The difference shows up when you try to union/sum a type with itself:

Ignoring bottom,

`Sum`

is the disjoint union of two copies of`Foo`

.The union of

`Foo`

with itself is just`Foo`

again.typescript 2 has sum types: https://blog.mariusschulz.com/2016/11/03/typescript-2-0-tagged-union-types

Product types as covered by Wikipedia. tl,dr; Haskell/ML/Rust shit.

I suspect we probably recognize them by another name and concrete example, and I also suspect somebody here might be able to bridge the theory with the practice. (nudge nudge @pushcx)

To give a simple version, Sum types are OR while Product types are AND. Tuples count as Product types and typescript and flow support them.

So are product types the same as intersection types? They’re not like tuples, but do express an “and” relationship. https://www.typescriptlang.org/docs/handbook/advanced-types.html

As I understand it, product types are different from intersection types in that product types vary depending on the order of the operands of the product, i.e. “A + B” (where + is the ‘product type operator’) differs from “B + A”.

A struct in C is a classic example of a product type; if you include two sub-structs of the same type (A + A), the elements of each differ, whereas in intersection types A & A would be the same as just A itself, and A & B = B & A.

(I think. Correct me if I’m wrong, someone more knowledgeable; this is based on my interactions with product/sum types in ML-y things, and only a little bit of interaction with intersection types while helping a friend debug some TypeScript, but I have no real-world experience with the latter.)

There is so much confusion in this subthread that I feel compelled to correct some of it:

`⊕`

), tensor products (`⊗`

), direct products (`×`

), unions (`|`

) and intersections (`&`

) are all different from each other.`(A ⊕ B) ⊕ C`

and`A ⊕ (B ⊕ C)`

are naturally isomorphic,`A ⊕ B`

and`B ⊕ A`

are naturally isomorphic, etc. None of them is idempotent.`(A | B) | C`

and`A | (B | C)`

are the same type,`A | B`

and`B | A`

are the same type,`A | A`

and`A`

are the same type, etc.`A ⊗ (B ⊕ C)`

and`(A ⊗ B) ⊕ (A ⊗ C)`

are naturally isomorphic.`A & (B | C)`

and`(A | B) & (A | C)`

are the same type, etc.`A`

and`B`

are isomorphic, and so are`C`

and`D`

, then so are`A ⊕ C`

and`B ⊕ D`

, etc. Category theorists call this “not being evil”.Crap. I really meant

`A & (B | C)`

and`(A & B) | (A & C)`

are isomorphic.Thank you!

I think a plain old C

`struct`

is a product type, and tagged`union`

s are sum types.Edit: nevermind, I’m very late to the party. :)

I suggest this link for a deeper and more exemplified comparison: https://djcordhose.github.io/flow-vs-typescript/flow-typescript-2.html#/