TypeScript is straight up one of the best technologies I work with, rivaled only possibly by giants like Postgres. It takes one of the worst parts of my day - refactoring Javascript code - and makes it straightforward and enjoyable.
TypeScript 2.0 goes beyond that and begins to push the envelope on what type systems can do. Recently I've been loving the combination of discriminated union types and nullable types. It means that you can have code like this:
function myFunction(x: number | null) {
if (x === null) {
return;
}
console.log(x + 1); // x is now a number
}
The argument to the function is x, which is either number or null (that's what number | null means). But the if statement ensures it's not null by exiting the function, so by the time you get to the log TypeScript has (correctly) set the type of x to be just number!
The types match up exactly with how you'd write the Javascript code. It's awesome and it just works.
> TypeScript 2.0 goes beyond that and begins to push the envelope on what type systems can do
Type systems could do stuff like that many, many years ago. I'm glad that you like these ideas, but let me assure you that TypeScript is far from pushing "what type systems can do".
I realize that I made a factual error in my post and I thank you for pointing that out, but to me your post reads as very condescending, to the point of being rude. It reminds me very clearly why I don't often post comments here.
That seems like a really weird thing to read into k_bx's post. I think you might want to try re-calibrating your "is this post meant personally"-meter :).
FWIW, I didn't see any condescension there. I got more of a "Oh, you ain't seen nothin' yet!" vibe from it. Obviously, YMMV.
> a claim with zero citations - not very useful at all.
Gradual typing isn't exactly a TypeScript invention: Typed Racket is gradually typed, has unions and intersections (which in turn date from further back than TR), refinement types, occurrence types, and even comes with a guarantee that typed code won't violate contracts. If the Racket runtime detects a contract violation, blame will always be assigned to untyped code. TR does more than TS does, and it was designed and implemented earlier.
> It sounded a bit condescending to me.
I didn't read k_bx's comment as belittlement of TypeScript: anything that makes JavaScript better is obviously a good thing! (Since we can't get rid of it.) But, as a matter of fact, TypeScript isn't pushing “what types can do”.
I'm not a native English speaker and didn't try to be rude, I'm sorry if you felt like that. I don't encourage you to post comments here more often though, posting more often doesn't necessary means it's good for you and everyone else.
And it adds nothing to the conversation, and has spawned an entire subthread of comments like ours which also adds nothing to the conversations. Its exactly the type of comment that should be banned from HN.
It's the classic "not invented here" syndrome, but on the level of languages. It's not enough to be able to have strong types in Javascript, they want people to stop writing Javascript, scrap the entire ecosystem, create all new browsers on every platform, and only write in their strongly typed language that's just as flawed as Javascript.
What I find very funny about PureScript is how it has these super-fancy types, designed from the ground up to express things like semigroupoids, lenses and profunctor-based optics... yet it doesn't have a numeric type better than JavaScript's good old floating points.
Just to be clear, this isn't meant as criticism, since I absolutely love how Haskell (and now PureScript too!) exploit algebraic structures to make code more reusable and robust. But the contrast between “can express fancy structures precisely” and “doesn't have precise arithmetic” is very amusing.
I don't have telepathic abilities to guess what exactly author meant. My goal was to let them know that type systems are much more developed than what TypeScript provides, and to encourage them to go out and learn them, read many great books and discover all the type-system goodness that's lying out there for free.
> TypeScript 2.0 goes beyond that and begins to push the envelope on what type systems can do. Recently I've been loving the combination of discriminated union types and nullable types.
As a side node, the FlowType system for JavaScript has had these features for over a year now, while TypeScript 2 is still in beta. These are the exact features which made us decide to go for FlowType instead of TypeScript 6 months ago. Happy to see that these two type systems now converge.
I haven't used Typescript either, but some of the differences are self evident to me. myFunction(x) can be called with any argument type; tooling can't detect an inappropriate type and output a warning/error(?), so you get to find certain mistakes the hard way; at runtime. "foo"+1 might make sense, but "foo"/1 is garbage, silently propagating 'undefined' up the stack in conventional Javascript, costing time and money for everyone. The user of myFunction(n: number | null) is provided with a meaningful signature during development, this saves time by providing precise information in a concise manner. Those of us that have spent time with statically typed languages and good tooling know what a blessing this is. The Typescript variant offers the possibility of a performance optimization; x+1 might compile down to a single instruction, as opposed to whatever runtime type check has to be invoked when the type of x isn't/can't be known at compile time. I don't know if that optimization is 'real' in practice given our contemporary javascript/typescript stack, but you can bet it will be eventually.
Inside the function you also have to continue using x as a number, like you wouldnt be able to accidentally pass it into a function accepting only string as argument etc.
Except for a few cases where Typescript let's you transpile ES6 syntax to JavaScript ES5, the compiler does not change your code; it just checks it for type errors.
The point of the example is that Typescript recently added support for non-null types, but is flexible enough to analyze where types have been further restricted by an early function return.
I haven't had the chance to try typescript yet but I absolutely love postgres, I mean I want to have sex with postgres. It is what is keeping our codebase somewhat sane. It pairs really well with the insufficiently typed javascript/nodejs. With postgres, at least the code interacting with state, the most perilous code, is typed, transactioned and manipulated in the functional sql way. I shudder to imagine in what mess we would be if we had gone with something like mongo.
This thread, with people like you that seem to get it, is definitely making me want to try typescript.
On that note, are there any documentation that explains the == and === operators in Typescript ? The language spec is only briefly acknowledges the existence of those operators.
function uhoh (x:string|number) {
if (typeof x === 'string') {
return x.length
} else {
return 'bar'
}
}
const a = uhoh('foo') //= string | number
const b = uhoh(3) //= string | number
You may already be aware of this, but it's semi-fixable in TS1:
function uhoh (x:string|number) {
if (typeof x === 'string') {
return x.length
} else {
return 'bar'
}
}
function uhoh (x:string): number;
function uhoh (x:number): string;
const a = uhoh('foo') //= number
const b = uhoh(3) //= string
Sort of. I tried the above and it reported the following error message:
error TS2354: No best common type exists among return expressions.
So at least it detects the problem. However the type inference algorithm should arguably return a union type here.
I find it good practice to always specify the return type of functions anyway. Then it will pick up cases where you return a type you didn't intend to; instead of just using a more general type it will tell you about the inconsistency.
Typescript does not infer union types for return types. You can explicitly annotate them just fine though.
I suppose the reasoning is that, when adding types to js, this is exactly the kind of bad behaviour you want to catch. But I'm not sure, perhaps there are just technical implications for not inferring union return types.
I am 99% certain that this is indeed the case. Non-nullable types are one of my favorite new additions to TypeScript.
But it goes further than that. TypeScript 2 adds control flow analysis, so adding to the top of a function that accepts a string or an array:
if (typeof someVarThatCanBeStringOrArrayOfStrings === "string") {
// turn string into array
}
any code below it can safely assume that the variable is string[], as well as the rest of the code that calls this function if this variable is returned.
You are almost correct -- it's just that it's not a "safe" assumption.
In your example, the JS interpreter will not throw an error when one provides a number (for example). Your code could break things. But why would this happen?
It's completely unrelated to TypeScript.
A number could be provided by the data, which in all likelihood is JSON from the network (eg: HTTP request or message queue body). Strongly typed languages will give you strongly typed data to protect you from this, but a dynamic language like JS doesn't afford you the same protection.
TypeScript doesn't mitigate this issue -- nor could it. TypeScript ensures your plumbing fits together, not that the sludge flowing through it won't cause a mess.
A strongly typed language will throw an exception before unexpected behavior can occur, JS on the other-hand will attempt to continue. It rarely happens, but since it does you can't say it safely works properly.
That's a good point, but I don't quite see how a strongly typed language fixes this issue. Could you elaborate on that?
If a strongly typed language receives data that is malformed, wouldn't the same problem arise? Isn't it always the case that you only have control over your own plumbing, and put up defenses to deal with external input?
(I have little experience with strongly typed languages, so I'm really interested to understand this a bit better)
TypeScript 2.0 goes beyond that and begins to push the envelope on what type systems can do. Recently I've been loving the combination of discriminated union types and nullable types. It means that you can have code like this:
The argument to the function is x, which is either number or null (that's what number | null means). But the if statement ensures it's not null by exiting the function, so by the time you get to the log TypeScript has (correctly) set the type of x to be just number!The types match up exactly with how you'd write the Javascript code. It's awesome and it just works.