{"id":1682,"date":"2018-05-31T16:34:58","date_gmt":"2018-05-31T16:34:58","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/typescript\/?p=1505"},"modified":"2019-02-28T09:56:24","modified_gmt":"2019-02-28T17:56:24","slug":"announcing-typescript-2-9-2","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/typescript\/announcing-typescript-2-9-2\/","title":{"rendered":"Announcing TypeScript 2.9"},"content":{"rendered":"<div style=\"font-size: 16px;\">Today we&#8217;re announcing the release of TypeScript 2.9!If you&#8217;re not familiar with TypeScript, it&#8217;s a language that adds optional static types to JavaScript. Those static types help make guarantees about your code to avoid typos and other silly errors. They can also provide nice things like code completions and easier project navigation thanks to tooling built around those types. When your code is run through the TypeScript compiler, you&#8217;re left with clean, readable, and standards-compliant JavaScript code, potentially rewritten to support much older browsers that only support ECMAScript 5 or even ECMAScript 3.<\/p>\n<p>If you can&#8217;t wait any longer, you can download TypeScript via <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.TypeScript.MSBuild\" rel=\"nofollow\">NuGet<\/a> or by running<\/p>\n<div class=\"highlight highlight-source-shell\">\n<pre>npm install -g typescript<\/pre>\n<\/div>\n<p>You can also get editor support for<\/p>\n<ul>\n<li><a href=\"http:\/\/download.microsoft.com\/download\/6\/D\/8\/6D8381B0-03C1-4BD2-AE65-30FF0A4C62DA\/2.9.1-TS-release-dev14update3-20180525.2\/TypeScript_Dev14Full.exe\" rel=\"nofollow\">Visual Studio 2015<\/a> (requires update 3)<\/li>\n<li><a href=\"http:\/\/download.microsoft.com\/download\/7\/0\/A\/70A6AC0E-8934-4396-A43E-445059F430EA\/2.9.1-TS-release-dev14update3-20180525.2\/TypeScript_SDK.exe\" rel=\"nofollow\">Visual Studio 2017<\/a> (requires 15.2 or later)<\/li>\n<li><a href=\"https:\/\/packagecontrol.io\/packages\/TypeScript\" rel=\"nofollow\">Sublime Text 3 via PackageControl<\/a><\/li>\n<li>Visual Studio Code with the next release, or <a href=\"https:\/\/code.visualstudio.com\/insiders\/\" rel=\"nofollow\">by trying the Insiders release of VS Code<\/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>This release brings some great editor features:<\/p>\n<ul>\n<li><a href=\"#rename-move-file\">Rename file and move declaration to new file<\/a><\/li>\n<li><a href=\"#unused-span-reporting\">Unused span reporting<\/a><\/li>\n<li><a href=\"#convert-getter-setter\">Convert property to getter\/setter<\/a><\/li>\n<\/ul>\n<p>And we also have core language\/compiler features:<\/p>\n<ul>\n<li><a href=\"#import-types\"><code style=\"color: #a31515;\">import()<\/code> types<\/a><\/li>\n<li><a href=\"#pretty-by-default\"><code style=\"color: #a31515;\">--pretty<\/code> by default<\/a><\/li>\n<li><a href=\"#json-imports\">Support for well-typed JSON imports<\/a><\/li>\n<li><a href=\"#type-arguments-tagged-template-strings\">Type arguments for tagged template strings<\/a><\/li>\n<li><a href=\"#updated-keyof\">Support for symbols and numeric literals in <code style=\"color: #a31515;\">keyof<\/code> and mapped object types<\/a><\/li>\n<\/ul>\n<p>We also have some minor <a href=\"#breaking-changes\">breaking changes<\/a> that you should keep in mind if upgrading.<\/p>\n<p>But otherwise, let&#8217;s look at what new features come with TypeScript 2.9!<\/p>\n<h2>Editor features<\/h2>\n<p>Because TypeScript&#8217;s language server is built in conjunction with the rest of the compiler, TypeScript can provide consistent cross-platform tooling that can be used on any editor. While we&#8217;ll dive into language improvements in a bit, it should only take a minute to cover these features which are often the most applicable to users, and, well, fun to see in action!<\/p>\n<h3><a name=\"rename-move-file\"><\/a>Rename file and move declaration to new file<\/h3>\n<p>After much community demand, two extremely useful refactorings are now available! First, this release of TypeScript allows users to move declarations to their own new files. Second, TypeScript 2.9 has functionality to rename files within your project while keeping import paths up-to-date.<\/p>\n<p><video src=\"http:\/\/devblogs.microsoft.com\/typescript\/wp-content\/uploads\/sites\/11\/2018\/05\/renameFileAndMoveToNewFile2.mp4\" autoplay=\"autoplay\" loop=\"loop\" muted=\"\" width=\"100%\" height=\"150\">\nMoving two interfaces to their own respective files, and then renaming those files while keeping all reference paths up to date.\n<\/video><\/p>\n<p>While not every editor has implemented these features yet, we expect they&#8217;ll be more broadly available soon.<\/p>\n<h3><a name=\"unused-span-reporting\"><\/a>Unused span reporting<\/h3>\n<p>TypeScript provices two lint-like flags: <code style=\"color: #a31515;\">--noUnusedLocals<\/code> and <code style=\"color: #a31515;\">--noUnusedParameters<\/code>. These options provide errors when certain declarations are found to be unused; however, while this information is generally useful, errors can be a bit much.<\/p>\n<p>TypeScript 2.9 has functionality for editors to surface these as &#8220;unused&#8221; suggestion spans. Editors are free to display these as they wish. As an example, Visual Studio Code will be displaying these as grayed-out text.<\/p>\n<p><a href=\"https:\/\/camo.githubusercontent.com\/7232ea79f660fa515950f4ba1235fa027f1809de\/68747470733a2f2f6d73646e7368617265642e626c6f622e636f72652e77696e646f77732e6e65742f6d656469612f323031382f30352f756e7573656453756767657374696f6e732e706e67\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/camo.githubusercontent.com\/7232ea79f660fa515950f4ba1235fa027f1809de\/68747470733a2f2f6d73646e7368617265642e626c6f622e636f72652e77696e646f77732e6e65742f6d656469612f323031382f30352f756e7573656453756767657374696f6e732e706e67\" alt=\"A parameter being grayed out as an unused declaration\" \/><\/a><\/p>\n<h3><a name=\"convert-getter-setter\"><\/a>Convert property to getter\/setter<\/h3>\n<p>Thanks to community contributor <a href=\"https:\/\/github.com\/Kingwl\">Wenlu Wang<\/a>, TypeScript 2.9 supports converting properties to get- and set- accessors.<\/p>\n<p><video src=\"http:\/\/devblogs.microsoft.com\/typescript\/wp-content\/uploads\/sites\/11\/2018\/05\/generateGetterSetter.mp4\" autoplay=\"autoplay\" loop=\"loop\" muted=\"\" width=\"65%\" height=\"150\">\nGenerating a get- and set-accessor from a class property declaration.\n<\/video><\/p>\n<h2><a name=\"import-types\"><\/a><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<\/div>\n<p>In other cases, there are simply things that you 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 mode 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<\/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<\/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><a name=\"pretty-by-default\"><\/a><code style=\"color: #a31515; font-size: 29px;\">--pretty<\/code> by default<\/h2>\n<p>TypeScript&#8217;s <code style=\"color: #a31515;\">--pretty<\/code> mode has been around for a while, and is meant to provide a friendlier console experience. Unfortunately it&#8217;s been opt-in for fear of breaking changes. However, this meant that users often never knew <code style=\"color: #a31515;\">--pretty<\/code> existed.<\/p>\n<p>To minimize breaking changes, we&#8217;ve made <code style=\"color: #a31515;\">--pretty<\/code> the default when TypeScript can reasonably detect that it&#8217;s printing output to a terminal (or really, whatever Node considers to be a TTY device). Users who want to turn <code style=\"color: #a31515;\">--pretty<\/code> off may do so by specifying <code style=\"color: #a31515;\">--pretty false<\/code> on the command line. Programs that rely on TypeScript&#8217;s output should adjust the spawned process&#8217;s TTY options.<\/p>\n<h2><a name=\"json-imports\"><\/a>Support for well-typed JSON imports<\/h2>\n<p>TypeScript is now able to import JSON files as input files when using the <code style=\"color: #a31515;\">node<\/code> strategy for <code style=\"color: #a31515;\">moduleResolution<\/code>. This means you can use <code style=\"color: #a31515;\">json<\/code> files as part of their project, and they&#8217;ll be well-typed!<\/p>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\">\/\/ .\/tsconfig.json\r\n{\r\n    \"compilerOptions\": {\r\n        \"module\": \"commonjs\",\r\n        \"resolveJsonModule\": true,\r\n        \"esModuleInterop\": true\r\n        \"outDir\": \"lib\"\r\n    },\r\n    \"include\": [\"src\"]\r\n}<\/pre>\n<\/div>\n<div class=\"highlight highlight-source-js\">\n<pre class=\"lang:default decode:true\">\/\/ .\/src\/settings.json\r\n{\r\n    \"dry\": false,\r\n    \"debug\": false\r\n}<\/pre>\n<\/div>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">\/\/ .\/src\/foo.ts\r\nimport settings from \".\/settings.json\";\r\n\r\nsettings.debug === true;  \/\/ Okay\r\nsettings.dry === 2;       \/\/ Error! Can't compare a `boolean` and `number`<\/pre>\n<\/div>\n<p>These JSON files will also carry over to your output directory so that things &#8220;just work&#8221; at runtime.<\/p>\n<h2><a name=\"type-arguments-tagged-template-strings\"><\/a>Type arguments for tagged template strings<\/h2>\n<p>If you use tagged template strings, you might be interested in some of the improvements in TypeScript 2.9.<\/p>\n<p>Most of the time when calling generic functions, TypeScript can infer type arguments. However, there are times where type arguments can&#8217;t be inferred. For example, one might imagine an API like the following:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">export interface RenderedResult {\r\n    \/\/ ...\r\n}\r\n\r\nexport interface TimestampedProps {\r\n    timestamp: Date;\r\n}\r\n\r\nexport function timestamped&lt;OtherProps&gt;(\r\n    component: (props: TimestampedProps &amp; OtherProps) =&gt; RenderedResult):\r\n        (props: OtherProps) =&gt; RenderedResult {\r\n    return props =&gt; {\r\n        const timestampedProps =\r\n            Object.assign({}, props, { timestamp: new Date() });\r\n        return component(timestampedProps);\r\n    }\r\n}<\/pre>\n<\/div>\n<p>Here, let&#8217;s assume a library where &#8220;components&#8221; are functions which take objects and return some rendered content. The idea is that <code style=\"color: #a31515;\">timestamped<\/code> will take a component that may use a <code style=\"color: #a31515;\">timestamp<\/code> property (from <code style=\"color: #a31515;\">TimestampedProps<\/code>) and some other properties (from <code style=\"color: #a31515;\">OtherProps<\/code>), and return a new component which only takes properties specified in <code style=\"color: #a31515;\">OtherProps<\/code>.<\/p>\n<p>Unfortunately there&#8217;s a problem with inference when using <code style=\"color: #a31515;\">timestamped<\/code> naively:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">declare function createDiv(contents: string | RenderedContent): RenderedContent;\r\n\r\nconst TimestampedMessage = timestamped(props =&gt; createDiv(`\r\n    Message opened at : ${props.timestamp}\r\n    Message contents\\n${props.contents}\r\n`));<\/pre>\n<\/div>\n<p>Here, TypeScript infers the wrong type for <code style=\"color: #a31515;\">props<\/code> when calling <code style=\"color: #a31515;\">timestamped<\/code> because it can&#8217;t find any candidates for <code style=\"color: #a31515;\">OtherProps<\/code>. <code style=\"color: #a31515;\">OtherProps<\/code> gets the type <code style=\"color: #a31515;\">{}<\/code>, and <code style=\"color: #a31515;\">props<\/code> is then assigned the type <code style=\"color: #a31515;\">TimestampedProps &amp; {}<\/code> which is undesirable.<\/p>\n<p>We can get around this with an explicit annotation on <code style=\"color: #a31515;\">props<\/code>:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">interface MessageProps {\r\n    contents: string;\r\n}\r\n\r\n\/\/        Notice this intersection type vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\r\nconst TimestampedMessage = timestamped((props: MessageProps &amp; TimestampedProps) =&gt; \/*...*\/);<\/pre>\n<\/div>\n<p>But we would prefer not to write as much; the type system already knows <code style=\"color: #a31515;\">TimestampedProps<\/code> will be part of the type; it just needs to know what <code style=\"color: #a31515;\">OtherProps<\/code> will be, so we can specify that explicitly.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">interface MessageProps {\r\n    contents: string;\r\n}\r\n\r\nconst TimestampedMessage = timestamped&lt;MessageProps&gt;(props =&gt; createDiv(`\r\n    Message opened at : ${props.timestamp.toLocaleString()}\r\n    Message contents\\n${props.contents}\r\n`));<\/pre>\n<\/div>\n<p>Whew! Great! But what does that have to do with tagged template strings?<\/p>\n<p>Well, the point here is that we the users were able to give type arguments when the type system had a hard time figuring things out on our invocations. It&#8217;s not ideal, but it at least it was possible.<\/p>\n<p>But tagged template strings are <em>also<\/em> a type of invocation. Tagged template strings actually invoke functions, but up until TypeScript 2.9, they support type arguments at all.<\/p>\n<p>For tagged template strings, this can be useful for libraries that work like <a href=\"https:\/\/www.styled-components.com\/\" rel=\"nofollow\">styled-components<\/a>:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">interface StyleProps {\r\n    themeName: string;\r\n}\r\n\r\ndeclare function styledInput&lt;OtherProps&gt;(\r\n    strs: TemplateStringsArray, \r\n    ...fns: ((props: OtherProps &amp; StyleProps) =&gt; string)[]):\r\n        React.Component&lt;OtherProps&gt;;<\/pre>\n<\/div>\n<p>Similar to the above example, TypeScript would have no way to infer the type of <code style=\"color: #a31515;\">OtherProps<\/code> if the functions passed to <code style=\"color: #a31515;\">fns<\/code> were not annotated:<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">export interface InputFormProps {\r\n    invalidInput: string;\r\n}\r\n\r\n\/\/ Error! Type 'StyleProps' has no property 'invalidInput'.\r\nexport const InputForm = styledInput `\r\n    color:\r\n        ${({themeName}) =&gt; themeName === 'dark' ? 'black' : 'white'};\r\n    border-color: ${({invalidInput}) =&gt; invalidInput ? 'red' : 'black'};\r\n`;<\/pre>\n<\/div>\n<p>TypeScript now 2.9 allows type arguments to be placed on tagged template strings, and makes this just as easy as a regular function call!<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">export interface InputFormProps {\r\n    invalidInput: string;\r\n}\r\n\r\nexport const InputForm = styledInput&lt;InputFormProps&gt; `\r\n    color:\r\n        ${({themeName}) =&gt; themeName === 'dark' ? 'black' : 'white'};\r\n    border-color: ${({invalidInput}) =&gt; invalidInput ? 'red' : 'black'};\r\n`;<\/pre>\n<\/div>\n<p>In the above example, <code style=\"color: #a31515;\">themeName<\/code> and <code style=\"color: #a31515;\">invalidInput<\/code> are both well-typed. TypeScript knows they are both <code style=\"color: #a31515;\">string<\/code>s, and would have told us if we&#8217;d misspelled either.<\/p>\n<h2><a name=\"updated-keyof\"><\/a>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 <code style=\"color: #a31515;\">number<\/code> and 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<\/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 remove <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}<\/pre>\n<\/div>\n<p>If you have code that&#8217;s more broadly applicable and can handle more than just <code style=\"color: #a31515;\">string<\/code>s, you should be able to substitute <code style=\"color: #a31515;\">string<\/code> with <code style=\"color: #a31515;\">string | number | symbol<\/code>, or use the built-in type alias <code style=\"color: #a31515;\">PropertyKey<\/code>.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">function 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<\/div>\n<p>Alternatively, you 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<p>If you intend on using <code style=\"color: #a31515;\">--keyofStringsOnly<\/code> and migrating off, instead of <code style=\"color: #a31515;\">PropertyKey<\/code>, you can create a type alias on <code style=\"color: #a31515;\">keyof any<\/code>, which is equivalent to <code style=\"color: #a31515;\">string | number | symbol<\/code> under normal circumstances, but becomes <code style=\"color: #a31515;\">string<\/code> when <code style=\"color: #a31515;\">--keyofStringsOnly<\/code> is set.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">type KeyofBase = keyof any;<\/pre>\n<\/div>\n<h2><a name=\"breaking-changes\"><\/a>Breaking changes<\/h2>\n<h3><code style=\"color: #a31515; font-size: 29px;\">keyof<\/code> types include symbolic\/numeric properties<\/h3>\n<p>As mentioned above, <code style=\"color: #a31515;\">keyof<\/code> types (also called &#8220;key query types&#8221;) 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>. You can correct your code&#8217;s assumptions, or revert to the old behavior 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<\/div>\n<h3><code style=\"color: #a31515; font-size: 29px;\">--pretty<\/code> on by default<\/h3>\n<p>Also mentioned above, <code style=\"color: #a31515;\">--pretty<\/code> is now turned on by default, though this may be a breaking change for some workflows.<\/p>\n<h3>Trailing commas not allowed on rest parameters<\/h3>\n<p>Trailing commas can no longer occur after <code style=\"color: #a31515;\">...rest<\/code>-parameters, as in the following.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true\">function pushElement(\r\n        foo: number,\r\n        bar: string,\r\n        ...rest: any[], \/\/ error!\r\n    ) {\r\n    \/\/ ...\r\n}<\/pre>\n<\/div>\n<p>This break was added for conformance with ECMAScript, as trailing commas are not allowed to follow rest parameters in the specification. Trailing commas should simply be removed following this syntax.<\/p>\n<h3>Unconstrained type parameters are no longer assignable to <code style=\"color: #a31515;\">object<\/code> in <code style=\"color: #a31515;\">strictNullChecks<\/code><\/h3>\n<p>The 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<\/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 of <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\/\/           vvvvvvvvvvvvvv\r\nfunction f&lt;T extends object&gt;(x: T) {\r\n    const y: object | null | undefined = x;\r\n}<\/pre>\n<\/div>\n<h3><code style=\"color: #a31515; font-size: 29px;\">never<\/code> can no longer be iterated over<\/h3>\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.<\/p>\n<div class=\"highlight highlight-source-ts\">\n<pre class=\"lang:default decode:true  \">declare let foo: never;\r\nfor (let prop in foo) {\r\n    \/\/ Error! `foo` has type `never`.\r\n}<\/pre>\n<\/div>\n<p>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 hope you&#8217;re as excited about the improvements to TypeScript 2.9 as we are &#8211; but save some excitement for TypeScript 3.0, where we&#8217;re aiming to deliver an experience around project-to-project references, a new <code style=\"color: #a31515;\">unknown<\/code> type, a stricter <code style=\"color: #a31515;\">any<\/code> type, and more!<\/p>\n<p>As always, you can keep an eye on <a href=\"https:\/\/github.com\/Microsoft\/TypeScript\/wiki\/Roadmap\">the TypeScript roadmap<\/a> to see what we&#8217;re working on for our next release (as well as anything we didn&#8217;t get the chance to mention in this blog post for this release). We also have nightly releases so you can try things out on your machine and give us your feedback early on. You can even try installing it now (<code style=\"color: #a31515;\">npm install -g typescript@next<\/code>) and play around with the new <code style=\"color: #a31515;\">unknown<\/code> type.<\/p>\n<p>Let us know what you think of this release over <a href=\"http:\/\/twitter.com\/typescriptlang\/\" rel=\"nofollow\">on Twitter<\/a> or in the comments below, and feel free to report issues and suggestions filing <a href=\"https:\/\/github.com\/Microsoft\/TypeScript\/issues\">a GitHub issue<\/a>.<\/p>\n<p>Happy Hacking!<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Today we&#8217;re announcing the release of TypeScript 2.9!If you&#8217;re not familiar with TypeScript, it&#8217;s a language that adds optional static types to JavaScript. Those static types help make guarantees about your code to avoid typos and other silly errors. They can also provide nice things like code completions and easier project navigation thanks to tooling [&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-1682","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 2.9!If you&#8217;re not familiar with TypeScript, it&#8217;s a language that adds optional static types to JavaScript. Those static types help make guarantees about your code to avoid typos and other silly errors. They can also provide nice things like code completions and easier project navigation thanks to tooling [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/1682","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=1682"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/posts\/1682\/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=1682"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/categories?post=1682"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/typescript\/wp-json\/wp\/v2\/tags?post=1682"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}