{"id":1455,"date":"2018-05-16T20:34:56","date_gmt":"2018-05-16T20:34:56","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/typescript\/?p=1455"},"modified":"2019-02-28T12:06:01","modified_gmt":"2019-02-28T20:06:01","slug":"announcing-typescript-2-9-rc","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-2-9-rc\/","title":{"rendered":"Announcing TypeScript 2.9 RC"},"content":{"rendered":"<p>Today we&#8217;re excited to announce and get some early feedback with TypeScript 2.9&#8217;s Release Candidate. To get started with the RC, you can access it <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.TypeScript.MSBuild\" rel=\"nofollow\">through NuGet<\/a>, or use npm with the following command:<\/p>\n<div class=\"highlight highlight-source-shell\">\n<pre class=\"lang:default decode:true\">npm install -g typescript@rc<\/pre>\n<\/div>\n<p>You can also get editor support by<\/p>\n<ul>\n<li><a href=\"http:\/\/download.microsoft.com\/download\/6\/D\/8\/6D8381B0-03C1-4BD2-AE65-30FF0A4C62DA\/2.9.0-TS-release-dev14update3-20180514.1\/TypeScript_Dev14Full.exe\" rel=\"nofollow\">Downloading for Visual Studio 2015<\/a> (with <a href=\"https:\/\/www.visualstudio.com\/en-us\/news\/releasenotes\/vs2015-update3-vs\" rel=\"nofollow\">Update 3<\/a>)<\/li>\n<li><a href=\"http:\/\/download.microsoft.com\/download\/7\/0\/A\/70A6AC0E-8934-4396-A43E-445059F430EA\/2.9.0-TS-release-dev14update3-20180514.1\/TypeScript_SDK.exe\" rel=\"nofollow\">Downloading for Visual Studio 2017<\/a> (for version 15.2 or later)<\/li>\n<li>Following directions for <a href=\"https:\/\/code.visualstudio.com\/Docs\/languages\/typescript#_using-newer-typescript-versions\" rel=\"nofollow\">Visual Studio Code<\/a> and <a href=\"https:\/\/github.com\/Microsoft\/TypeScript-Sublime-Plugin\/#note-using-different-versions-of-typescript\">Sublime Text<\/a>.<\/li>\n<\/ul>\n<p>Let&#8217;s jump into some highlights of the Release Candidate!<\/p>\n<h2>Support for symbols and numeric literals in <code style=\"color: #a31515; font-size: 29px;\">keyof<\/code> and mapped object types<\/h2>\n<p>TypeScript&#8217;s <code style=\"color: #a31515;\">keyof<\/code> operator is a useful way to query the property names of an existing 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}\r\n\r\n\/\/ Equivalent to the type\r\n\/\/  \"name\" | \"age\"\r\ntype PersonPropertiesNames = keyof Person;<\/pre>\n<\/div>\n<p>Unfortunately, because <code style=\"color: #a31515;\">keyof<\/code> predates TypeScript&#8217;s ability to reason about <code style=\"color: #a31515;\">unique symbol<\/code> types, <code style=\"color: #a31515;\">keyof<\/code> never recognized symbolic keys.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">const baz = Symbol(\"baz\");\r\n\r\ninterface Thing {\r\n    foo: string;\r\n    bar: number;\r\n    [baz]: boolean; \/\/ this is a computed property type\r\n}\r\n\r\n\/\/ Error in TypeScript 2.8 and earlier!\r\n\/\/ `typeof baz` isn't assignable to `\"foo\" | \"bar\"`\r\nlet x: keyof Thing = baz;<\/pre>\n<\/div>\n<p>TypeScript 2.9 changes the behavior of <code style=\"color: #a31515;\">keyof<\/code> to factor in both unique symbols as well as numeric literal types. As such, the above example now compiles as expected. <code style=\"color: #a31515;\">keyof Thing<\/code> now boils down to the type <code style=\"color: #a31515;\">\"foo\" | \"bar\" | typeof baz<\/code>.<\/p>\n<p>With this functionality, mapped object types like <code style=\"color: #a31515;\">Partial<\/code>, <code style=\"color: #a31515;\">Required<\/code>, or <code style=\"color: #a31515;\">Readonly<\/code> also recognize symbolic and numeric property keys, and no longer drop properties named by symbols:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true \">type Partial&lt;T&gt; = {\r\n    [K in keyof T]: T[K]\r\n}\r\n\r\ninterface Thing {\r\n    foo: string;\r\n    bar: number;\r\n    [baz]: boolean;\r\n}\r\n\r\ntype PartialThing = Partial&lt;Thing&gt;;\r\n\r\n\/\/ This now works correctly and is equivalent to\r\n\/\/\r\n\/\/   interface PartialThing {\r\n\/\/       foo?: string;\r\n\/\/       bar?: number;\r\n\/\/       [baz]?: boolean;\r\n\/\/   }<\/pre>\n<p>&nbsp;<\/p>\n<\/div>\n<p>Unfortunately this is a breaking change for any usage where users believed that for any type <code style=\"color: #a31515;\">T<\/code>, <code style=\"color: #a31515;\">keyof T<\/code> would always be assignable to a <code style=\"color: #a31515;\">string<\/code>. Because symbol- and numeric-named properties invalidate this assumption, we expect some minor breaks which we believe to be easy to catch. In such cases, there are several possible workarounds.<\/p>\n<p>If you have code that&#8217;s really meant to only operate on string properties, you can use <code style=\"color: #a31515;\">Extract&lt;keyof T, string&gt;<\/code> to restrict <code style=\"color: #a31515;\">symbol<\/code> and <code style=\"color: #a31515;\">number<\/code> inputs:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true \">function useKey&lt;T, K extends Extract&lt;keyof T, string&gt;&gt;(obj: T, k: K) {\r\n    let propName: string = k;\r\n    \/\/ ...\r\n}\r\nIf you have code that's more broadly applicable and can handle more than just strings, you should be able to substitute string with string | number | symbol, or use the built-in type alias PropertyKey.\r\n\r\nfunction useKey&lt;T, K extends keyof T&gt;(obj: T, k: K) {\r\n    let propName: string | number | symbol = k; \r\n    \/\/ ...\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<\/div>\n<p>Alternatively, users can revert to the old behavior under the <code style=\"color: #a31515;\">--keyofStringsOnly<\/code> compiler flag, but this is meant to be used as a transitionary flag.<\/p>\n<h2><code style=\"color: #a31515; font-size: 29px;\">import()<\/code> types<\/h2>\n<p>One long-running pain-point in TypeScript has been the inability to reference a type in another module, or the type of the module itself, without including an import at the top of the file.<\/p>\n<p>In some cases, this is just a matter of convenience &#8211; you might not want to add an import at the top of your file just to describe a single type&#8217;s usage. For example, to reference the type of a module at an arbitrary location, here&#8217;s what you&#8217;d have to write before TypeScript 2.9:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true \">import * as _foo from \"foo\";\r\n\r\nexport async function bar() {\r\n    let foo: typeof _foo = await import(\"foo\");\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<\/div>\n<p>In other cases, there are simply things that users can&#8217;t achieve today &#8211; for example, referencing a type within a module in the global scope is impossible today. This is because a file with any imports or exports is considered a module, so adding an import for a type in a global script file will automatically turn that file into a module, which drastically changes things like scoping rules and strict module within that file.<\/p>\n<p>That&#8217;s why TypeScript 2.9 is introducing the new <code style=\"color: #a31515;\">import(...)<\/code> type syntax. Much like ECMAScript&#8217;s proposed <code style=\"color: #a31515;\">import(...)<\/code> expressions, import types use the same syntax, and provide a convenient way to reference the type of a module, or the types which a module contains.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true \">\/\/ foo.ts\r\nexport interface Person {\r\n    name: string;\r\n    age: number;\r\n}\r\n\r\n\/\/ bar.ts\r\nexport function greet(p: import(\".\/foo\").Person) {\r\n    return `\r\n        Hello, I'm ${p.name}, and I'm ${p.age} years old.\r\n    `;\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<\/div>\n<p>Notice we didn&#8217;t need to add a top-level import specify the type of <code style=\"color: #a31515;\">p<\/code>. We could also rewrite our example from above where we awkwardly needed to reference the type of a module:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true \">export async function bar() {\r\n    let foo: typeof import(\".\/foo\") = await import(\".\/foo\");\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<\/div>\n<p>Of course, in this specific example <code style=\"color: #a31515;\">foo<\/code> could have been inferred, but this might be more useful with something like <a href=\"https:\/\/github.com\/Microsoft\/TypeScript\/wiki\/Writing-a-Language-Service-Plugin#setup-and-initialization\">the TypeScript language server plugin API<\/a>.<\/p>\n<h2>Breaking changes<\/h2>\n<h3><code style=\"color: #a31515; font-size: 26px;\">keyof<\/code> types include symbolic\/numeric properties<\/h3>\n<p>As mentioned above, key queries\/<code style=\"color: #a31515;\">keyof<\/code> types now include names that are <code style=\"color: #a31515;\">symbol<\/code>s and <code style=\"color: #a31515;\">number<\/code>s, which can break some code that assumes <code style=\"color: #a31515;\">keyof T<\/code> is assignable to <code style=\"color: #a31515;\">string<\/code>. Users can avoid this by using the <code style=\"color: #a31515;\">--keyofStringsOnly<\/code> compiler option:<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true \">\/\/ tsconfig.json\r\n{\r\n    \"compilerOptions\": {\r\n        \"keyofStringsOnly\": true\r\n    }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<\/div>\n<h3>Trailing commas not allowed on rest parameters<\/h3>\n<p><a href=\"https:\/\/github.com\/Microsoft\/TypeScript\/pull\/22262\">#22262<\/a>\nThis break was added for conformance with ECMAScript, as trailing commas are not allowed to follow rest parameters in the specification.<\/p>\n<h3>Unconstrained type parameters are no longer assignable to <code style=\"color: #a31515; font-size: 26px;\">object<\/code> in <code style=\"color: #a31515; font-size: 26px;\">strictNullChecks<\/code><\/h3>\n<p><a href=\"https:\/\/github.com\/Microsoft\/TypeScript\/issues\/24013\">#24013<\/a>\nThe following code now errors:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true \">function f&lt;T&gt;(x: T) {\r\n    const y: object | null | undefined = x;\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<\/div>\n<p>Since generic type parameters can be substituted with any primitive type, this is a precaution TypeScript has added under <code style=\"color: #a31515;\">strictNullChecks<\/code>. To fix this, you can add a constraint on <code style=\"color: #a31515;\">object<\/code>:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true \">\/\/ We can add an upper-bound constraint here.\r\n\/\/           vvvvvvvvvvvvvvv\r\nfunction f&lt;T extends object&gt;(x: T) {\r\n    const y: object | null | undefined = x;\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<\/div>\n<h3><code style=\"color: #a31515; font-size: 26px;\">never<\/code> can no longer be iterated over<\/h3>\n<p><a href=\"https:\/\/github.com\/Microsoft\/TypeScript\/pull\/22964\">#22964<\/a><\/p>\n<p>Values of type <code style=\"color: #a31515;\">never<\/code> can no longer be iterated over, which may catch a good class of bugs. Users can avoid this behavior by using a type assertion to cast to the type <code style=\"color: #a31515;\">any<\/code> (i.e. <code style=\"color: #a31515;\">foo as any<\/code>).<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>We try to keep our plans easily discoverable <a href=\"https:\/\/github.com\/Microsoft\/TypeScript\/wiki\/Roadmap\">on the TypeScript roadmap<\/a> for everything else that&#8217;s coming in 2.9 and beyond. TypeScript 2.9 proper should arrive towards the end of the month, but to make that successful, we need all the help we can get, so download the RC today and let us know what you think!<\/p>\n<p>Feel free to <a href=\"https:\/\/github.com\/Microsoft\/TypeScript\/issues\/new\">drop us a line on GitHub if you run into any problems<\/a>, and let others know how you feel about this RC on Twitter and in the comments below!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today we&#8217;re excited to announce and get some early feedback with TypeScript 2.9&#8217;s Release Candidate. To get started with the RC, you can access it through NuGet, or use npm with the following command: npm install -g typescript@rc You can also get editor support by Downloading for Visual Studio 2015 (with Update 3) Downloading for [&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-1455","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-typescript"],"acf":[],"blog_post_summary":"<p>Today we&#8217;re excited to announce and get some early feedback with TypeScript 2.9&#8217;s Release Candidate. To get started with the RC, you can access it through NuGet, or use npm with the following command: npm install -g typescript@rc You can also get editor support by Downloading for Visual Studio 2015 (with Update 3) Downloading for [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/1455","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=1455"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/1455\/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=1455"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/categories?post=1455"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/tags?post=1455"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}