1. Number of existing type definitions in DefTyped vs. FlowTyped and packages that provide typings. TypeScript has way more type definitions
2. Tooling, TypeScript has a much better tooling support
3. Project popularity: number of downloads, GitHub issues and pull requests etc. TypeScript is much more popular.
Syntax and personal opinions was not part of our decision making process.
The main takeaway for me is that TS is much much less sound than Flow. That means it checks less invariants which in turn makes you less trust it...
Consider the following code which is valid (!) in TS:
let promisedString: Promise<string> = new Promise(
resolve => {
// Perfectly valid in TypeScript!
resolve(42)
}
)
Another downside of TS is poor type inference. It requires to annotate each top level function while Flow only requires to annotate exported functions.Even the following simple piece of code will make TS ask you to annotate doAddition function:
export function addition(a: number, b: number) {
return doAddition(a, b)
}
function doAddition(a, b) {
return a + b
}
I'm really glad Flow doesn't force me into it.Edit: spelling
let promisedString: Promise<string> = new Promise<string>(
resolve => {
// Perfectly valid in TypeScript!
resolve(undefined)
}
)
EDIT: no, I was wrong — Bluebird typings won't allow this behaviour but they force me to annotate both the binding and the Promise constructor call: let promisedString: Promise<string> = new Promise<string>(
resolve => {
resolve(42) // type error here, ok
}
)
That's surprising TS ships with such unsafe typings for ES2015 Promise API...Hm... no.
First, note that this is with noImplicitAny activated. You can check this in TS playground.
Then if we inspect what typings TS have for ES2015 Promises[1] and for Bluebird[2], you can clearly see that those are identical in this case..
[1]: https://github.com/Microsoft/TypeScript/blob/master/lib/lib....
[2]: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/mast...
error TS2322: Type 'Bluebird<{}>' is not assignable to type 'Bluebird<string>'.
And if I add the type parameter to the constructor... error TS2345: Argument of type '42' is not assignable to parameter of type 'string | Thenable<string>'
Re: your edit, you actually don't need that first typing. Typescript will infer the type of the promisedString.Ok, but still this is confusing, it can't infer the type of RHS given the annotated LHS? Intuitively there's nothing wrong with it and Flow does that well...
var cat = new Animal<Cat>(...); // yup! Animal<Cat> cat = new Animal(...); // Nope
I wonder if internally ts is treating these generic-accepting classes in the same way, where the generic is required?
let promisedString = new Promise<string>(
resolve => {
// Fails as expected in TypeScript!
resolve(42)
}
)For example:
function fn(a) {
const {b} = a;
console.log(b.c);
}
fn({});
This compiles without errors - but would fail at runtime. https://flow.org/try/#0PQKgBAAgZgNg9gdzCYAoVUCuA7AxgFwEs5swp...For your second example - it's a divisive issue. I believe that a Hindley-Milner style type resolver (what Flow uses) is more usable, but there is a strong argument against it too [0].
That's something I don't understand. Isn't that incorrect behaviour? Shouldn't TS try unify RHS and LHS?
In this case in Typescript it is generally more strict to add a type annotation to the generic than the LHS:
let promise = new Promise<string>((resolve) => resolve(42)) // This won't work
This is as much because the inference here that matters isn't between LHS and RHS but between generic arguments and function return inference.And in personal anecdote-space I've experience the exact opposite :)
What I like about TypeScript and which I think is "sound" compared to Flow is the whole experience and how it is backed by good tooling.
With TypeScript I can open almost "any" editor and expect it to understand and respect the typings of all my TypeScript code. It will correctly autocomplete, and tell me when I'm using undefined members.
Basically with TypeScript every part of the stack seems to work for me, the developer, to ensure I make the right decisions and get the assistance I need, at all time. That makes it feel like a very safe and sound language to write code in.
With flow? Well fuck that. From what I can tell, you get almost nothing.
You can run your compiler and see if it validates, but I've seen almost no editor-support worth mentioning, meaning that while the type-inference in the compiler may occasionally be better (but for how long? TS has a ton of momentum), the overall experience feels much less sound and much more fragile. Much more unsafe.
The type-declarations definitely feel as important as the way they are declared: they're mere comments. They're not real.
TypeScript:
- Structurally typed
- Enum types
- Mapped types
- Abstract classes
- Scoped class members (public, private, protected)
- Namespaces
Flow:
- Nominally typed
- Covariance/contravariance annotations
- Supertype annotations (via $Supertype type)
- Subtype annotations (via $Subtype type)
- Arity annotations (via $Pred type)
- Subtraction types (via $Diff type)
- Opt-in 2-way type resolver (via * type)
- Refer to nested type (via $PropertyType type)
Otherwise, the two are remarkably similar.
I've been using TS for a few years, and Flow for a few months. Please correct me if any of the above are wrong.
https://github.com/styfle/react-server-example-tsx/blob/mast...
The use case I like most about typescript is it makes refactoring and making changes really painless. For example, in an angular app, you may have a service that several components rely on. When changing a method signature in the service, you'll get compile-time info about any other usages of that service, and you feel a lot more confident about making changes without something dumb slipping through the cracks and causing bugs in production.
This confidence generally lends itself to less fear of change and more willingness to refactor, which leads to a better/cleaner codebase.
Aside from that, I love the JSDoc comments showing up as you type, especially if you're working on a team in which you may not know 100% what everyone has worked on.
Other features I use every day and love:
-automatic/generated import statements
-type definitions for libraries (most have solid documentation)
-control-flow logic checking (you'll find more bugs than you think with this and it encourages more defensive programming)
-transpiling down to support older browsers (babel does this too but it's nice to have it built in)
Edit: I forgot to go into the "cons" list here.
-there's some finagling you'll have to do with some of the more poorly-written npm packages that strap themselves onto globals
-there's a slight learning curve
-you'll require a build step (with es6 if you're targeting es6-only browsers you can deploy just static files, but most people use webpack/babel anyway for older browser support and other things webpack gives you like bundling/minification/etc)
I'd like to note that this is done automatically in Visual Studio 2015 and on. You just save your .ts file and VS will create the .js file.
I'm not by nature keen on automatic behaviour, or files appearing wherever, and though I visited this story simply to check in on the state of a language I know less than I want about, I'm certain that I would want a proper build step even for tinkering, once I start in earnest. I've long been enthusiastic about TypeScript especially, but from a distance, unable to allocate time to take it seriously enough.
I think the state of js and environment is now at a point that, in my view at least, I should not begin the smallest project without a deep dive into the state of the language. I see things moving so fast, that - at least in my workplace where we've had teams stick together for years commonly (partnership!) - it would suck to find oneself misdirected by a aggressive assumption, or find oneself in a unloved cul - de - sac of dependencies.
Tl;dr js is IMO at a place where the pay off for deeply studying the state of the language, is substantial while risk of not deeply groking js are rising fast.
Personally, I think I shall better resort to getting a new shelf of good books, for my needs, but I do believe the risk reward is looking hairy for any casual users. (or hurried business management, in particular)
I'm a little surprised, given my understanding the impression I had of ts is the very broad aim is to reduce your error in code, (type safety only part of that) that VS will encourage casual / random deployments like this. I can't decide if it's a occasional convenience quite suited to weekend js ciders like me, or a omitted formality that I feel encourages poor or slack habits.
Funny thing is, I never once thought of firing up VS to write JavaScript before now. I have no need, but I'm just displaying my age when I note that visually my mind thinks of early Netscape view source spelunking and text editors, not a actual IDE and build system.
What keeps me, well into a fourth decade of programming, from using JavaScript I think is only the fact that I totally phase out at the state of the tool chain for js. My mind blanks. But there's so much to like, using js, that i hope it's not abandoned by time I get to really learning it. (forgive my humour, but my first real computing experience was on a Symbolics 3650, then spanking new. Last week wanting to show a friend what one looked like, I found kids veritably boarding them! (sorry for the kids part, but it's nuts I found such phrases creeping up on me, I'm lucky in looking less than my years, but when did I start saying things like "the kids are doing x"? I want to know what causes this, and if there's a cure!)
Edit: Typos, minor clarity
True, it _results in a bug. But when bug count gets high, and I see a noticeable percent originating from slacking habits, I start prowling to find who's been pulling too much overtime or something family is tiring them out. Nine out of ten times, it's someone who needs only firm advice to look after themselves better. Where I work age skews much higher than SV norms, so young children and other delights (not /s at all) have notable impact on code quality.
I quite commonly get a wood<>trees occlusion, when I'm thinking through my own habits, to visualize the world. I've just made documentation such a important part of my working life that I am constantly thinking through that structure. It began with a prospective business partner trying to blackmail my company in part by withholding key metadata for a important deal. The deal that founded my company, in fact. I know I was scarred badly by that. And this was a important friends, ten years my senior, without whose advice I would have..i don't know what other path... So I made self documenting a whole schedule in the partnership. Forget living off a LP interest in retirement, if you pull a stunt like the one that nearly bankrupted us before we started. (unlimited liability! We are since a limited partnership, but the fact we were a general partnership actually saved our houses on that first deal. The customer CEO actually noticed our names as one does put them on the letter head. Suddenly calls were made, subsidiary directors were gotten at home to listen up... Our customer CEO sussed how much we had on the line. The world changed in a instant. Not a small customer the kind you think might cate, either, DAX30! Edit to say I doubt any but a German boss would spot a partnership firm by letter head. &co KG is a very common incorporation form, UK L.P. also permits a limited entity as gp. UK lp can be domiciled wherever you like, too. If anyone will be helped by any experience i might offer, just drop me a line, I believe some of our long observations could have genuine assistive value for starting ventures. Specifically for any non UK nationals still wanting a post Brexit presence at minimum exposure. Banking for these partnerships can be tricky, or you may simply be blanked by confused staff, but I've has good experience i can relate if you need to bank in the UK for a project. N.b. UK L.P.s are not taxed at the corporate level, only your personal income can be taxed. The potential for compounding gains when yours small and growing, is nothing to be sniffed at)