TypeScript 3.9 is Coming!


Improvements in Inference and Promise.all

Speed Improvements

// @ts-expect-error Comments

Uncalled Function Checks in Conditional Expressions

Editor Improvements

Breaking Changes

Software Engineer | Studio XID, Inc.

Microsoft MVP

TypeScript Korea User Group Organizer

Electron Korea User Group Organizer

Marktube (Youtube)

Mark Lee

npm i typescript@3.9.1-rc -D

node_modules/.bin/tsc --init

touch index.ts
// 3.8.3

interface Foo {
  a: () => void;
}

interface Bar {
  b: () => void;
}

async function test(f: Promise<Foo>, b: Promise<Bar>) {
  const [foo, bar] = await Promise.all([f, b]);
  foo; // Foo
  bar; // Bar
}
// 3.8.3

interface Foo {
  a: () => void;
}

interface Bar {
  b: () => void;
}

async function test(f: Promise<Foo>, b: Promise<Bar | null>) {
  const [foo, bar] = await Promise.all([f, b]);
  foo; // Foo | null ???????
  bar; // Bar | null
}
// 3.9.1-rc

interface Foo {
  a: () => void;
}

interface Bar {
  b: () => void;
}

async function test(f: Promise<Foo>, b: Promise<Bar | null>) {
  const [foo, bar] = await Promise.all([f, b]);
  foo; // Foo
  bar; // Bar | null
}
  • large unions

  • intersections

  • conditional types

  • mapped types

// 3.8.3

function doStuff(abc: string, xyz: string) {
  assert(typeof abc === "string");
  assert(typeof xyz === "string");

  // do some stuff
}

expect(() => {
  // @ts-ignore
  doStuff(123, 456);
}).toThrow();
// 3.9.1-rc

function doStuff(abc: string, xyz: string) {
  assert(typeof abc === "string");
  assert(typeof xyz === "string");

  // do some stuff
}

expect(() => {
  // @ts-expect-error
  doStuff(123, 456);
}).toThrow();
// 3.9.1-rc

function doStuff(abc: string, xyz: string) {
  assert(typeof abc === "string");
  assert(typeof xyz === "string");

  // do some stuff
}

expect(() => {
  // @ts-expect-error
  doStuff('123', '456');
}).toThrow();
// 3.8.3

declare function hasImportantPermissions(): boolean;
declare function deleteAllTheImportantFiles(): void;

if (hasImportantPermissions) {
  deleteAllTheImportantFiles();
}

"내가 보니 함수는 항상 있는 것 같은데,

함수를 왜 호출하지 않고 쓰는 것이냐 ?"

라는 말을 하는 타입스크립트 컴파일러

(Uncalled Function Checks - 3.7)

// 3.8.3

declare function hasImportantPermissions(): boolean;
declare function deleteAllTheImportantFiles(): void;
declare function noop(): void;

hasImportantPermissions
  ? deleteAllTheImportantFiles()
  : noop();

hasImportantPermissions && deleteAllTheImportantFiles();

"내가 보니 함수는 항상 있는 것 같은데,

함수를 왜 호출하지 않고 쓰는 것이냐 ?"

라는 말을 하지 않는 타입스크립트 컴파일러

// 3.9.1-rc

declare function hasImportantPermissions(): boolean;
declare function deleteAllTheImportantFiles(): void;
declare function noop(): void;

hasImportantPermissions
  ? deleteAllTheImportantFiles()
  : noop();

hasImportantPermissions && deleteAllTheImportantFiles();

여전히

"내가 보니 함수는 항상 있는 것 같은데,

함수를 왜 호출하지 않고 쓰는 것이냐 ?"

라는 말을 하지 않는 타입스크립트 컴파일러

이제야

"내가 보니 함수는 항상 있는 것 같은데,

함수를 왜 호출하지 않고 쓰는 것이냐 ?"

라는 말을 하는 타입스크립트 컴파일러

  • CommonJS 스타일로 자동으로 임포트 구문 넣어줌

  • 함수로 추출할 때, 개행을 보존해서 만들어줌

// 3.8.3

function barPercentage(foo?: { bar: { baz: string } }) {
  foo?.bar!.baz; // string
}
// 3.9.1-rc

function barPercentage(foo?: { bar: { baz: string } }) {
  foo?.bar!.baz; // string | undefined
  (foo?.bar)!.baz; // string
}
// 3.8.3

<div>Navigate to: Menu Bar > Tools > Options</div>;
// 3.9.1-rc

<div>Navigate to: Menu Bar > Tools > Options</div>;
// 3.8.3

interface A {
  a: number; // notice this is 'number'
}

interface B {
  b: string;
}

interface C {
  a?: boolean; // notice this is 'boolean'
  b: string;
}

declare let x: A & B;
declare let y: C;

y = x;
// 3.9.1-rc

interface A {
  a: number; // notice this is 'number'
}

interface B {
  b: string;
}

interface C {
  a?: boolean; // notice this is 'boolean'
  b: string;
}

declare let x: A & B;
declare let y: C;

y = x;
// 3.8.3

declare function smushObjects<T, U>(x: T, y: U): T & U;

interface Circle {
  kind: "circle";
  radius: number;
}

interface Square {
  kind: "square";
  sideLength: number;
}

declare let x: Circle;
declare let y: Square;

const z = smushObjects(x, y);
z.kind;
z.radius;
z.sideLength;
// 3.9.1-rc

declare function smushObjects<T, U>(x: T, y: U): T & U;

interface Circle {
  kind: "circle";
  radius: number;
}

interface Square {
  kind: "square";
  sideLength: number;
}

declare let x: Circle;
declare let y: Square;

const z = smushObjects(x, y);
z.kind;
z.radius;
z.sideLength;

TypeScript 3.9 is Coming!

By Woongjae Lee

TypeScript 3.9 is Coming!

TypeScript Korea User Group Monthly Online Meetup (Apr.)

  • 895