Hey! guys, in this post I will be discussing the changes brought in by typescript 3.9. I will give some code examples and brief descriptions. Breaking Changes 1. Parsing differences in optional chaining & non-Null assertions Previous versions: In some cases, using optional chaining (?) with non-null assertions (!) alters the behavior of short-circuiting (optional chaining no longer works) Now (3.9): The above no longer happens and code is intuitive. { ec } ; Orders { orderDetail?: OrderDetail; } OrderDetail { item?: Item; } Item { price: ; } order: Orders = { orderDetail: }; itemPrice: = order.orderDetail?.item!.price; ec.l(itemPrice); ec.l(itemPrice); import from 'easy-console' interface // orderDetail: OrderDetail | undefined; interface // item: Item | undefined; interface number const undefined const number // // Before // trying to access property on undefined // v3.9 //undefined 2. Stricter checks on intersections and optional properties Previous versions: Types derived by using intersection can be assigned to other similar types without stricter checks on the underneath type properties. Now: There are stricter checks on the types when using the intersection types. So it will not work if the types are exactly not same. { ec } ; A { a: ; } B { b: ; } C { a?: ; b: ; } x: A & B = { a: , b: }; y: C = x; ec.l( , x); ec.l( , y); y: C = x; import from 'easy-console' interface number // notice this is 'number' interface string interface boolean // notice this is 'boolean' string const 1 `s` // Before const // Type 'number' is not assignable to type 'boolean'. `x>>` // { a: 1, b: `s` } `y>>` // { a: 1, b: `s` } // 3.9 const // error- Type 'number' is not assignable to type 'boolean'. 3. Stricter check on Intersections derived from different type properties Before: Intersection of types which have same properties with no overlapping type, collapses to never for that particular particular property. Now: Intersection of types which have same properties with nothing in common, collapses the whole intersection type to never. { ec } ; interface Category { : ; categoryName: string; level: number; } interface Product { : ; productName: string; productPrice: number; } type Group = Category & Product; group: Group = { : , : , : , : , : , }; ec.l( , group); ec.l( , group); import from 'easy-console' iam 'categoryType' iam 'productType' // 3.9 whole types becomes never const categoryName 'Laptops' level 1 productName 'Macbook' productPrice 1234 iAm "never say never" // in previous version only the particular type becomes // Before 'group.iAm =>' // previous version - error only on 'iAm' property // 3.9 'group.iAm =>' // version 3.9 - error on all properties 4. and are Now Invalid JSX Text Characters } > Now you cannot use them directly in .tsx files. You will get below errors. Unexpected token. Did you mean or ? Unexpected token. Did you mean or ? `{'>'}` `&gt;` `{'}'}` `&rbrace;` 5. Type Parameters That Extend any No Longer Act as any { ec } ; { ec.l( , arg.IwillNotGiveError); } { ec.l( , arg.IwillGiveError); } import from 'easy-console' < >( ) function foo T extends any arg: T 'arg.anyArguments' // previous versions no error < >( ) function foo T extends any arg: T 'arg.anyArguments' // 3.9 error Improvements 1. Improvements in Inference and Promise.all In certain cases when while using Promise.all(), the response types of the promises get mismatched in the result. This results in compile time error. This was observed mostly when an undefined type was present. Find below the codebox ( on older version). 2. // @ts-expect-error Comments It allows you to accept an error where there is a type error. For eg. In a scenario where you are writing a test, and you deliberately want to pass different types of values. How is it different from @ts-ignore ? @ts-expect-error will notify you when it is not required. describe( , () => { it( , () => { { expect(a).toBe( ); } expectErr( ); expectErr( ); }); }); 'Todo' 'sample test' ( ) function expectErr a: string 'string' // @ts-expect-error 1 // no error // @ts-expect-error "a" // error 3. Uncalled Function Checks in Conditional Expressions (?:) In previous versions, typescript was doing a check, whether we have called our functions while using conditions (such as if else) or not. But not on the using the conditional operators (? :). But now it supports the same. { } (hasImportantPermissions) { deleteAllTheImportantFiles(); } ( ): function hasImportantPermissions boolean // ... // Oops! if // ~~~~~~~~~~~~~~~~~~~~~~~ // This condition will always return true since the function is always defined. // Did you mean to call it instead? 4. Typescript now support "solution style" tsconfig.json files You can define the several tsconfig in one file, rather than placing in individual directory structure. { : [], : [ { : }, { : }, { : }, ] } // tsconfig.json "files" "references" "path" "./tsconfig.shared.json" "path" "./tsconfig.frontend.json" "path" "./tsconfig.backend.json" 5. Other minor improvements CommonJS auto-imports imports like JS (using require statement ) Compile time improvements Editor improvements- improved support for sublime, vscode, nightly Editor Code Actions - properly preserve spacing/line breaks Happy Hacking! For more detailed information and issue specific pull request, refer the following link: https://devblogs.microsoft.com/typescript/announcing-typescript-3-9-beta/