{"id":1920,"date":"2018-10-08T23:22:17","date_gmt":"2018-10-09T06:22:17","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/typescript\/?p=1920"},"modified":"2019-02-27T22:18:27","modified_gmt":"2019-02-28T06:18:27","slug":"announcing-typescript-3-1","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-3-1\/","title":{"rendered":"Announcing TypeScript 3.1"},"content":{"rendered":"<p>Today we&#8217;re announcing the release of TypeScript 3.1!If you haven&#8217;t heard of TypeScript, it&#8217;s a language that builds on top of modern JavaScript and adds static type-checking. When you write TypeScript code, you can use a tool like the TypeScript compiler to remove type-specific constructs, and rewrite any newer ECMAScript code to something that older browsers &amp; runtimes can understand. Additionally, using types means that your tools can analyze your code more easily, and provide you with a rock-solid editing experience giving you things like code-completion, go-to-definition, and quick fixes. On top of that, it&#8217;s all free, open-source, and cross-platform, so if you&#8217;re interested in learning more, <a href=\"https:\/\/www.typescriptlang.org\/\" rel=\"nofollow\">check out our website<\/a>.<\/p>\n<p>If you just want to get started with the latest version of TypeScript, you can get it <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.TypeScript.MSBuild\" rel=\"nofollow\">through NuGet<\/a> or via npm by running<\/p>\n<pre class=\"lang:default decode:true\">npm install -g typescript<\/pre>\n<p>You can also get editor support for<\/p>\n<ul>\n<li><a href=\"http:\/\/download.microsoft.com\/download\/7\/0\/A\/70A6AC0E-8934-4396-A43E-445059F430EA\/3.1.1-TS-release-dev14-update3-20180926.1\/TypeScript_SDK.exe\" rel=\"nofollow\">Visual Studio 2017<\/a> (for version 15.2 or later).<\/li>\n<li><a href=\"http:\/\/download.microsoft.com\/download\/6\/D\/8\/6D8381B0-03C1-4BD2-AE65-30FF0A4C62DA\/3.1.1-TS-release-dev14-update3-20180926.1\/TypeScript_Dev14Full.exe\" rel=\"nofollow\">Visual Studio 2015<\/a> (which requires update 3).<\/li>\n<li>For Visual Studio Code <a href=\"https:\/\/code.visualstudio.com\/insiders\/\" rel=\"nofollow\">by installing the Insiders release<\/a> (until the next release of VS Code).<\/li>\n<li><a href=\"https:\/\/packagecontrol.io\/packages\/TypeScript\" rel=\"nofollow\">Sublime Text 3 via PackageControl<\/a>.<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/Microsoft\/TypeScript\/wiki\/TypeScript-Editor-Support\">Other editors<\/a> may have different update schedules, but should all have excellent TypeScript support soon as well.<\/p>\n<p>Let&#8217;s take a look at what this release of TypeScript brings us. Feel free to use the list below to jump around this post a bit.<\/p>\n<ul>\n<li><a href=\"#mappable-tuple-and-array-types\">Mappable tuple and array types<\/a><\/li>\n<li><a href=\"#easier-properties-on-function-declarations\">Easier properties on function declarations<\/a><\/li>\n<li><a href=\"#version-redirects-for-TypeScript-via-typesVersions\">Version redirects for TypeScript via <code style=\"color: #a31515;\">typesVersions<\/code><\/a><\/li>\n<li><a href=\"#refactor-from-then-to-await\">Refactor from <code style=\"color: #a31515;\">.then()<\/code> to <code style=\"color: #a31515;\">await<\/code><\/a><\/li>\n<li><a href=\"#breaking-changes\">Breaking changes<\/a><\/li>\n<\/ul>\n<h2 id=\"mappable-tuple-and-array-types\">Mappable tuple and array types<\/h2>\n<p>Mapping over values in a list is one of the most common patterns in programming. As an example, let&#8217;s take a look at the following JavaScript code:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true  \">function stringifyAll(...elements) {\r\n    return elements.map(x =&gt; String(x));\r\n}<\/pre>\n<\/div>\n<p>The <code style=\"color: #a31515;\">stringifyAll<\/code> function takes any number of values, converts each element to a string, places each result in a new array, and returns that array. If we want to have the most general type for <code style=\"color: #a31515;\">stringifyAll<\/code>, we&#8217;d declare it as so:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">declare function stringifyAll(...elements: unknown[]): Array&lt;string&gt;;<\/pre>\n<\/div>\n<p>That basically says, &#8220;this thing takes any number of elements, and returns an array of <code style=\"color: #a31515;\">string<\/code>s&#8221;; however, we&#8217;ve lost a bit of information about <code style=\"color: #a31515;\">elements<\/code> in that transformation.<\/p>\n<p>Specifically, the type system doesn&#8217;t remember the number of elements user passed in, so our output type doesn&#8217;t have a known length either. We can do something like that with overloads:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">declare function stringifyAll(...elements: []): string[];\r\ndeclare function stringifyAll(...elements: [unknown]): [string];\r\ndeclare function stringifyAll(...elements: [unknown, unknown]): [string, string];\r\ndeclare function stringifyAll(...elements: [unknown, unknown, unknown]): [string, string, string];\r\n\/\/ ... etc<\/pre>\n<\/div>\n<p><em>Ugh<\/em>. And we didn&#8217;t even cover taking <em>four<\/em> elements yet. You end up special-casing all of these possible overloads, and you end up with what we like to call the &#8220;death by a thousand overloads&#8221; problem. Sure, we could use conditional types instead of overloads, but then you&#8217;d have a bunch of nested conditional types.<\/p>\n<p><em>If only<\/em> there was a way to uniformly map over each of the types here&#8230;<\/p>\n<p>Well, TypeScript already has something that sort of does that. TypeScript has a concept called a mapped object type which can generate new types out of existing ones. For example, given the following <code style=\"color: #a31515;\">Person<\/code> type,<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">interface Person {\r\n    name: string;\r\n    age: number;\r\n    isHappy: boolean;\r\n}<\/pre>\n<\/div>\n<p>we might want to convert each property to a string as above:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">interface StringyPerson {\r\n    name: string;\r\n    age: string;\r\n    isHappy: string;\r\n}\r\n\r\nfunction stringifyPerson(person: Person) {\r\n    const result = {} as StringyPerson;\r\n    for (const prop in person) {\r\n        result[prop] = String(person[prop]);\r\n    }\r\n    return result;\r\n}<\/pre>\n<\/div>\n<p>Though notice that <code style=\"color: #a31515;\">stringifyPerson<\/code> is pretty general. We can abstract the idea of <code style=\"color: #a31515;\">Stringify<\/code>-ing types using a mapped object type over the properties of any given type:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">type Stringify&lt;T&gt; = {\r\n    [K in keyof T]: string\r\n};<\/pre>\n<\/div>\n<p>For those unfamiliar, we read this as &#8220;for every property named <code style=\"color: #a31515;\">K<\/code> in <code style=\"color: #a31515;\">T<\/code>, produce a new property of that name with the type <code style=\"color: #a31515;\">string<\/code>.<\/p>\n<p>and rewrite our function to use that:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">function stringifyProps&lt;T&gt;(obj: T) {\r\n    const result = {} as Stringify&lt;T&gt;;\r\n    for (const prop in obj) {\r\n        result[prop] = String(obj[prop]);\r\n    }\r\n    return result;\r\n}\r\n\r\nstringifyProps({ hello: 100, world: true }); \/\/ has type `{ hello: string, world: string }`<\/pre>\n<\/div>\n<p>Seems like we have what we want! However, if we tried changing the type of <code style=\"color: #a31515;\">stringifyAll<\/code> to return a <code style=\"color: #a31515;\">Stringify<\/code>:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true \">declare function stringifyAll&lt;T extends unknown[]&gt;(...elements: T): Stringify&lt;T&gt;;<\/pre>\n<p>&nbsp;<\/p>\n<\/div>\n<p>And then tried calling it on an array or tuple, we&#8217;d only get something that&#8217;s <em>almost<\/em> useful prior to TypeScript 3.1. Let&#8217;s give it a shot on an older version of TypeScript like 3.0:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">let stringyCoordinates = stringifyAll(100, true);\r\n\r\n\/\/ No errors!\r\nlet first: string = stringyCoordinates[0];\r\nlet second: string = stringyCoordinates[1];<\/pre>\n<\/div>\n<p>Looks like our tuple indexes have been mapped correctly! Let&#8217;s check the grab the length now and make sure that&#8217;s right:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">let len: 2 = stringyCoordinates.length\r\n\/\/     ~~~\r\n\/\/ Type 'string' is not assignable to type '2'.<\/pre>\n<\/div>\n<p>Uh. <code style=\"color: #a31515;\">string<\/code>? Well, let&#8217;s try to iterate on our coordinates.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">   stringyCoordinates.forEach(x =&gt; console.log(x));\r\n\/\/ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n\/\/ Cannot invoke an expression whose type lacks a call signature. Type 'String' has no compatible call signatures.<\/pre>\n<\/div>\n<p>Huh? What&#8217;s causing this gross error message? Well our <code style=\"color: #a31515;\">Stringify<\/code> mapped type not only mapped our tuple members, it also mapped over the methods of <code style=\"color: #a31515;\">Array<\/code>, as well as the <code style=\"color: #a31515;\">length<\/code> property! So <code style=\"color: #a31515;\">forEach<\/code> and <code style=\"color: #a31515;\">length<\/code> both have the type <code style=\"color: #a31515;\">string<\/code>!<\/p>\n<p>While technically consistent in behavior, the majority of our team felt that this use-case should just work. Rather than introduce a new concept for mapping over a tuple, mapped object types now just &#8220;do the right thing&#8221; when iterating over tuples and arrays. This means that if you&#8217;re already using existing mapped types like <code style=\"color: #a31515;\">Partial<\/code> or <code style=\"color: #a31515;\">Required<\/code> from <code style=\"color: #a31515;\">lib.d.ts<\/code>, they automatically work on tuples and arrays now.<\/p>\n<p>While very general, you might note that this functionality means that TypeScript is now better-equipped to express functions similar to <code style=\"color: #a31515;\">Promise.all<\/code>. While that specific change hasn&#8217;t made its way into this release, it may be coming in the near future.<\/p>\n<h2 id=\"easier-properties-on-function-declarations\">Easier properties on function declarations<\/h2>\n<p>In JavaScript, functions are just objects. This means we can tack properties onto them as we please:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\">export function readFile(path) {\r\n    \/\/ ...\r\n}\r\n\r\nreadFile.async = function (path, callback) {\r\n    \/\/ ...\r\n}<\/pre>\n<\/div>\n<p>TypeScript&#8217;s traditional approach to this has been an extremely versatile construct called <code style=\"color: #a31515;\">namespace<\/code>s (a.k.a. &#8220;internal modules&#8221; if you&#8217;re old enough to remember). In addition to organizing code, namespaces support the concept of <em>value-merging<\/em>, where you can add properties to classes and functions in a declarative way:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">export function readFile() {\r\n    \/\/ ...\r\n}\r\n\r\nexport namespace readFile {\r\n    export function async() {\r\n        \/\/ ...\r\n    }\r\n}<\/pre>\n<\/div>\n<p>While perhaps elegant for their time, the construct hasn&#8217;t aged well. ECMAScript modules have become the preferred format for organizing new code in the broader TypeScript &amp; JavaScript community, and namespaces are TypeScript-specific. Additionally, namespaces don&#8217;t merge with <code style=\"color: #a31515;\">var<\/code>, <code style=\"color: #a31515;\">let<\/code>, or <code style=\"color: #a31515;\">const<\/code> declarations, so code like the following (which is motivated by <code style=\"color: #a31515;\">defaultProps<\/code> from React):<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">export const FooComponent =&gt; ({ name }) =&gt; (\r\n    &lt;div&gt;Hello! I am {name}&lt;\/div&gt;\r\n);\r\n\r\nFooComponent.defaultProps = {\r\n    name: \"(anonymous)\",\r\n};<\/pre>\n<\/div>\n<p>can&#8217;t even simply be converted to<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">export const FooComponent =&gt; ({ name }) =&gt; (\r\n    &lt;div&gt;Hello! I am {name}&lt;\/div&gt;\r\n);\r\n\r\n\/\/ Doesn't work!\r\nnamespace FooComponent {\r\n    export const defaultProps = {\r\n        name: \"(anonymous)\",\r\n    };\r\n}<\/pre>\n<\/div>\n<p>All of this collectively can be frustrating since it makes migrating to TypeScript harder.<\/p>\n<p>Given all of this, we felt that it would be better to make TypeScript a bit &#8220;smarter&#8221; about these sorts of patterns. In TypeScript 3.1, for any function declaration or <code style=\"color: #a31515;\">const<\/code> declaration that&#8217;s initialized with a function, the type-checker will analyze the containing scope to track any added properties. That means that both of the examples &#8211; both our <code style=\"color: #a31515;\">readFile<\/code> as well as our <code style=\"color: #a31515;\">FooComponent<\/code> examples &#8211; work without modification in TypeScript 3.1!<\/p>\n<p>As an added bonus, this functionality in conjunction with TypeScript 3.0&#8217;s support for <code style=\"color: #a31515;\">JSX.LibraryManagedAttributes<\/code> makes migrating an untyped React codebase to TypeScript <em>significantly<\/em> easier, since it understands which attributes are optional in the presence of <code style=\"color: #a31515;\">defaultProps<\/code>:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">\/\/ TypeScript understands that both are valid:\r\n&lt;FooComponent \/&gt;\r\n&lt;FooComponent name=\"Nathan\" \/&gt;<\/pre>\n<\/div>\n<h2 id=\"version-redirects-for-typescript-via-typesversions\">Version redirects for TypeScript via <code style=\"color: #a31515; font-size: 29px;\">typesVersions<\/code><\/h2>\n<p>Many TypeScript and JavaScript users love to use the bleeding-edge features of the languages and tooling. While we love the exuberance that drives this, it can sometimes create a difficult situation for library maintainers where maintainers are forced to choose between supporting new TypeScript features and not breaking older versions of TypeScript.<\/p>\n<p>As an example, if you maintain a library which uses the <code style=\"color: #a31515;\">unknown<\/code> type from TypeScript 3.0, any of your consumers using earlier versions will be broken. There unfortunately isn&#8217;t a way to provide types for pre-3.0 versions of TypeScript while also providing types for 3.0 and later.<\/p>\n<p>That is, until now. When using Node module resolution in TypeScript 3.1, when TypeScript cracks open a <code style=\"color: #a31515;\">package.json<\/code> file to figure out which files it needs to read, it first looks at a new field called <code style=\"color: #a31515;\">typesVersions<\/code>. A <code style=\"color: #a31515;\">package.json<\/code> with a <code style=\"color: #a31515;\">typesVersions<\/code> field might look like this:<\/p>\n<div class=\"highlight highlight-source-json\">\n<pre class=\"lang:default decode:true\">{\r\n  \"name\": \"package-name\",\r\n  \"version\": \"1.0\",\r\n  \"types\": \".\/index.d.ts\",\r\n  \"typesVersions\": {\r\n    \"&gt;=3.1\": { \"*\": [\"ts3.1\/*\"] }\r\n  }\r\n}\r\n<\/pre>\n<\/div>\n<p>This <code style=\"color: #a31515;\">package.json<\/code> tells TypeScript to check whether the current version of TypeScript is running. If it&#8217;s 3.1 or later, it figures out the path you&#8217;ve imported relative to the package, and reads from the package&#8217;s <code style=\"color: #a31515;\">ts3.1<\/code> folder. That&#8217;s what that <code style=\"color: #a31515;\">{ \"*\": [\"ts3.1\/*\"] }<\/code> means &#8211; if you&#8217;re familiar with path mapping today, it works exactly like that.<\/p>\n<p>So in the above example, if we&#8217;re importing from <code style=\"color: #a31515;\">\"package-name\"<\/code>, we&#8217;ll try to resolve from <code style=\"color: #a31515;\">[...]\/node_modules\/package-name\/ts3.1\/index.d.ts<\/code> (and other relevant paths) when running in TypeScript 3.1. If we import from <code style=\"color: #a31515;\">package-name\/foo<\/code>, we&#8217;ll try to look for <code style=\"color: #a31515;\">[...]\/node_modules\/package-name\/ts3.1\/foo.d.ts<\/code> and <code style=\"color: #a31515;\">[...]\/node_modules\/package-name\/ts3.1\/foo\/index.d.ts<\/code>.<\/p>\n<p>What if we&#8217;re not running in TypeScript 3.1 in this example? Well, if none of the fields in <code style=\"color: #a31515;\">typesVersions<\/code> get matched, TypeScript falls back to the <code style=\"color: #a31515;\">types<\/code> field, so here TypeScript 3.0 and earlier will be redirected to <code style=\"color: #a31515;\">[...]\/node_modules\/package-name\/index.d.ts<\/code>.<\/p>\n<h3 id=\"matching-behavior\">Matching behavior<\/h3>\n<p>The way that TypeScript decides on whether a version of the compiler &amp; language matches is by using Node&#8217;s <a href=\"https:\/\/github.com\/npm\/node-semver#ranges\">semver ranges<\/a>.<\/p>\n<h3 id=\"multiple-fields\">Multiple fields<\/h3>\n<p><code style=\"color: #a31515;\">typesVersions<\/code> can support multiple fields where each field name is specified by the range to match on.<\/p>\n<div class=\"highlight highlight-source-json\">\n<pre class=\"lang:default decode:true\">{\r\n  \"name\": \"package-name\",\r\n  \"version\": \"1.0\",\r\n  \"types\": \".\/index.d.ts\",\r\n  \"typesVersions\": {\r\n    \"&gt;=3.2\": { \"*\": [\"ts3.2\/*\"] },\r\n    \"&gt;=3.1\": { \"*\": [\"ts3.1\/*\"] }\r\n  }\r\n}<\/pre>\n<\/div>\n<p>Since ranges have the potential to overlap, determining which redirect applies is order-specific. That means in the above example, even though both the <code style=\"color: #a31515;\">&gt;=3.2<\/code> and the <code style=\"color: #a31515;\">&gt;=3.1<\/code> matchers support TypeScript 3.2 and above, reversing the order could have <em>totally<\/em> different behavior, so the above sample would not be equivalent to the following.<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\">{\r\n  \"name\": \"package-name\",\r\n  \"version\": \"1.0\",\r\n  \"types\": \".\/index.d.ts\",\r\n  \"typesVersions\": {\r\n    \/\/ NOTE: this won't work!\r\n    \"&gt;=3.1\": { \"*\": [\"ts3.1\/*\"] },\r\n    \"&gt;=3.2\": { \"*\": [\"ts3.2\/*\"] }\r\n  }\r\n}<\/pre>\n<\/div>\n<h2 id=\"refactor-from-then-to-await\">Refactor from <code style=\"color: #a31515; font-size: 29px;\">.then()<\/code> to <code style=\"color: #a31515; font-size: 29px;\">await<\/code><\/h2>\n<p>The editing experience we know and love for TypeScript is actually built directly on top of the compiler itself, and so our team is directly responsible for bringing you features like refactorings in tools like Visual Studio, VS Code, and others.<\/p>\n<p>Thanks to a lot of fantastic work from Elizabeth Dinella who interned with us this past summer, TypeScript 3.1 now has a refactoring to convert functions that return promises constructed with chains of <code style=\"color: #a31515;\">.then()<\/code> and <code style=\"color: #a31515;\">.catch()<\/code> calls to <code style=\"color: #a31515;\">async<\/code> functions that leverage <code style=\"color: #a31515;\">await<\/code>. You can see this in action in the video below.<\/p>\n<p><video src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/2018\/09\/3-1-thenToAwait.mp4\" autoplay=\"autoplay\" loop=\"loop\" muted=\"\" width=\"678\" height=\"150\">\n<\/video><\/p>\n<h2 id=\"breaking-changes\">Breaking Changes<\/h2>\n<p>Our team always strives to avoid introducing breaking changes, but unfortunately there are some to be aware of for TypeScript 3.1.<\/p>\n<h3 id=\"vendor-specific-declarations-removed\">Vendor-specific declarations removed<\/h3>\n<p>TypeScript 3.1 now generates parts of <code style=\"color: #a31515;\">lib.d.ts<\/code> (and other built-in declaration file libraries) using Web IDL files provided from the WHATWG DOM specification. While this means that <code style=\"color: #a31515;\">lib.d.ts<\/code> will be easier to keep up-to-date, many vendor-specific types have been removed. We&#8217;ve covered this in more detail <a href=\"https:\/\/github.com\/Microsoft\/TypeScript\/wiki\/Breaking-Changes\">on our wiki<\/a>.<\/p>\n<h3 id=\"differences-in-narrowing-functions\">Differences in narrowing functions<\/h3>\n<p>Using the <code style=\"color: #a31515;\">typeof foo === \"function\"<\/code> type guard may provide different results when intersecting with relatively questionable union types composed of <code style=\"color: #a31515;\">{}<\/code>, <code style=\"color: #a31515;\">Object<\/code>, or unconstrained generics.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">function foo(x: unknown | (() =&gt; string)) {\r\n    if (typeof x === \"function\") {\r\n        let a = x()\r\n    }\r\n}<\/pre>\n<\/div>\n<p>You can read more on <a href=\"https:\/\/github.com\/Microsoft\/TypeScript\/wiki\/Breaking-Changes#narrowing-functions-now-intersects--object-and-unconstrained-generic-type-parameters\">the breaking changes section of our wiki<\/a>.<\/p>\n<h2 id=\"whats-next\">What&#8217;s next<\/h2>\n<p>You can take a look at <a href=\"https:\/\/github.com\/Microsoft\/TypeScript\/wiki\/Roadmap\">our roadmap<\/a> for things we haven&#8217;t covered here, as well as to get a sense of what&#8217;s coming up for the next release of TypeScript.<\/p>\n<p>As an example of something we haven&#8217;t covered much here, TypeScript 3.1 also brought a series of error message improvements which should give helpful tips, and which will do a better job of accurately explaining where things might&#8217;ve gone wrong when you hit an error. Additionally, as an example of something new in store, 3.2 will provide strictly-typed <code style=\"color: #a31515;\">call<\/code>\/<code style=\"color: #a31515;\">bind<\/code>\/<code style=\"color: #a31515;\">apply<\/code> on function types. So keep an eye on the roadmap to see how things develop.<\/p>\n<p>As always, we hope this release continues to make you happier and more productive. If you have any feedback, feel free to <a href=\"https:\/\/github.com\/Microsoft\/TypeScript\/issues\">file an issue<\/a> or <a href=\"https:\/\/twitter.com\/typescriptlang\" rel=\"nofollow\">reach out over Twitter<\/a>.<\/p>\n<p>Thanks, and happy hacking!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today we&#8217;re announcing the release of TypeScript 3.1!If you haven&#8217;t heard of TypeScript, it&#8217;s a language that builds on top of modern JavaScript and adds static type-checking. When you write TypeScript code, you can use a tool like the TypeScript compiler to remove type-specific constructs, and rewrite any newer ECMAScript code to something that older [&hellip;]<\/p>\n","protected":false},"author":381,"featured_media":1797,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1920","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-typescript"],"acf":[],"blog_post_summary":"<p>Today we&#8217;re announcing the release of TypeScript 3.1!If you haven&#8217;t heard of TypeScript, it&#8217;s a language that builds on top of modern JavaScript and adds static type-checking. When you write TypeScript code, you can use a tool like the TypeScript compiler to remove type-specific constructs, and rewrite any newer ECMAScript code to something that older [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/1920","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/users\/381"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/comments?post=1920"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/1920\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/media\/1797"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/media?parent=1920"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/categories?post=1920"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/tags?post=1920"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}