typescript update log 🚀 Chinese speed reading (updated to 4.5), continuous update

Give priority to personal learning and facilitate others 😉

Starting address: https://github.com/any86/ts-l... The content of this article will also be updated continuously

🔥 Reading instructions

Due to the limited personal ability, this paper only filters the knowledge points related to type / syntax from the "typescript update log". The versions before 3.1 are some basic knowledge, so only some contents are extracted If there are any mistakes, please give more advice and help

Note: changes in type inference (relaxation / narrowing) and configuration items, as well as new syntax selections in ECMA

v4.5

Add wait type

Gets the type of the resolve value of prmove

// Promise<number>
const p = Promise.resolve(123);
// Awaited<Promise<number>> === number
type B = Awaited<typeof p>;

// Type parameter is not Promise type,
// Then do not process and return directly
type S = Awaited<string>; // string

Import name modifier "type"

The previous version supported the syntax of "import type {xx} from 'xxx'". Now it supports marking a single import item with "type"

import { someFunc, type BaseType } from "./some-module.js";

Check whether the private property of the class exists

Synchronous compatible ecma syntax

class Person {
    #name: string;
    constructor(name: string) {
        this.#name = name;
    }
    equals(other: unknown) {
        return other &&
            typeof other === "object" &&
            #name in other && // <-  🔥 New grammar
            this.#name === other.#name;
    }
}

Import assertion

Synchronization is compatible with ecma syntax. It makes runtime judgment on the imported file, and ts does not make any judgment

import obj from "./something.json" assert { type: "json" };

And the syntax of the "import" function:

const obj = await import("./something.json", {
  assert: { type: "json" },
});

v4.4

More intelligent type protection

Common types of protection are as follows:

function nOrs() {
  return Math.random() > 0.5 ? 123 : "abc";
}
let input = nOrs();
if (typeof input === "number") {
  input++;
}

If typeof input === 'number' is abstracted into a variable, type protection will fail before version 4.4, but ts can be protected correctly in version 4.4

function nOrs() {
  return Math.random() > 0.5 ? 123 : "abc";
}
const input = nOrs();
const isNumber = typeof input === "number";
if (isNumber) {
  // Invalid, cannot know input is of type number
  input++;
}

Note: the required protected variables must be "const variables" or "realonly attributes", such as the input above and the "n" attribute below

interface A {
  readonly n: number | string;
}

const a: A = { n: Math.random() > 0.5 ? "123" : 321 };
const isNumber = typeof a.n === "number";
if (isNumber) {
  // r is number
  const r = a.n;
}

Deeper type protection

The range of union types can be narrowed through attribute judgment

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; sideLength: number };

function area(shape: Shape): number {
  const isCircle = shape.kind === "circle";
  if (isCircle) {
    // We know we have a circle here!
    return Math.PI * shape.radius ** 2;
  } else {
    // We know we're left with a square here!
    return shape.sideLength ** 2;
  }
}

âš¡ Add a key that supports symbol type as object type

Previously, only "string | number" was supported, resulting in incomplete description of Object type keys. Now it is solved

interface Test1 {
  [k: string | number | symbol]: any;
}

type Test2 = {
  [k in string | number | symbol]: any;
};

static block in class

Synchronization supports es new syntax

class Foo {
  static #count = 0;

  get count() {
    return Foo.#count;
  }

  static {
    try {
      const lastInstances = loadLastInstances();
      Foo.#count += lastInstances.length;
    } catch {}
  }
}

v4.3

override keyword

"override" is the syntax provided to the class to mark whether the attribute / method in the subclass overrides the attribute / method with the same name of the parent class

class A {}

class B extends A {
  // Hint: override cannot be used because there is no "a" field in the base class
  override a() {}
}

@ link in comment

Click to jump to the specified code

/**
 * To be called 70 to 80 days after {@link plantCarrot}.
 */
function harvestCarrot(carrot: Carrot) {}
/**
 * Call early in spring for best results. Added in v2.1.0.
 * @param seed Make sure it's a carrot seed!
 */
function plantCarrot(seed: Seed) {
  // TODO: some gardening
}

v4.2

Yuanzu supports optional symbols

let c: [string, string?] = ["hello"];
c = ["hello", "world"];

Primitive ancestor type definitions support the use of '...' anywhere

However, optional elements (?) are not allowed in the tail And "..." appear

let foo: [...string[], number];

foo = [123];
foo = ["hello", 123];
foo = ["hello!", "hello!", "hello!", 123];

let bar: [boolean, ...string[], boolean];

bar = [true, false];
bar = [true, "some text", false];
bar = [true, "some", "separated", "text", false];

Error example

let StealersWheel: [...Clown[], "me", ...Joker[]];
// A rest element cannot follow another rest element.

let StringsAndMaybeBoolean: [...string[], boolean?];
// An optional element cannot follow a rest element.

v4.1

Template string type

The syntax is the same as that of ` ` 'in es6, except that it is used to package types:

type World = "world";
// hello world
type Greeting = `hello ${World}`;

type Color = "red" | "blue";
type Quantity = "one" | "two";
// "one fish" | "two fish" | "red fish" | "blue fish"
type SeussFish = `${Quantity | Color} fish`;

New string type

The ts system adds Uppercase / Lowercase / Capitalize / Uncapitalize types

// ABC
type S1 = Uppercase<"abc">;
// abc
type S2 = Lowercase<"ABC">;
// Abc
type S3 = Capitalize<"abc">;
// aBC
type S4 = Uncapitalize<"ABC">;

Use as in the key in structure

After obtaining the key, it is used to obtain the value, but not the key, only the value, and then re label the key

type PPP<T> = {
  [K in keyof T as "ww"]: T[K];
};

// type A = {ww:1|'2'}
type A = PPP<{ a: 1; b: "2" }>;

v4.0

The rest term of Yuanzu can be deduced accurately

Previously, get the type of tuple except the first element:

function tail<T extends any[]>(arr: readonly [any, ...T]) {
  const [_ignored, ...rest] = arr;
  return rest;
}

const myTuple = [1, 2, 3, 4] as const;
const myArray = ["hello", "world"];

const r1 = tail(myTuple);
// const r1: [2, 3, 4]
const r2 = tail([...myTuple, ...myArray] as const);
// const r2: [2, 3, 4, ...string[]]

rest elements can appear anywhere in tuples, not just at the end!

It requires "..." The following element must be a tuple, and only the last element can be "..."+ Array

type Strings = [string, string];
type Numbers = [number, number];
type StrStrNumNumBool = [...Strings, ...Numbers, boolean];
type StrStrNumNumBool = [...[string], string, ...string[]];

Tuple elements support labeling

It is mainly to be compatible with the definition of function parameters, because function parameters have parameter names

type Range = [start: number, end: number];

The assignment of constructor in class can directly deduce the type of attribute

When defining attributes, you can omit the type annotation

class A {
  // At this point, a is directly deduced to be of type number
  // Type can be omitted, a cannot be omitted
  a;
  constructor() {
    this.a = 1;
  }
}

The parameter of catch in try/catch becomes unknown

Judgment or assertion is required before use

try {
  // ...
} catch (e) {
  e; // unknown
}

/*_ @deprecated _/

Label deprecated

v3.9

// @ts-expect-error

It is used to shield errors. Different from the motivation of "/ / @ TS ignore", the main use scenario of "/ / @ TS expect error" is that you deliberately make errors, such as test cases

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

// You want to test the incoming digital parameters, but ts will automatically infer errors, which is not what you want, so add "/ / @ ts expect error"
expect(() => {
  // @ts-expect-error
  doStuff(123, 456);
}).toThrow();

v3.8

import type / export type

New syntax added for type import and export only.

import type { SomeThing } from "./some-module.js";
export type { SomeThing };

Private property '#' of class

Unlike the private modifier, # the private attribute syntax of synchronous ecma cannot be accessed outside the class even after it is compiled into js

class Person {
  #name: string;
  constructor(name: string) {
    this.#name = name;
  }
  greet() {
    console.log(`Hello, my name is ${this.#name}!`);
  }
}

export * as ns

Export syntax, synchronized with ecma2020 syntax

export * as utilities from "./utilities.js";

await keyword for top-level scope

The syntax synchronized with ecma must be used within the module, so there must be at least one "empty export {}"

const response = await fetch("...");
const greeting = await response.text();
console.log(greeting);
// Make sure we're a module
export {};

Another limitation is the configuration item: "target" is above es2017 and "module" is "esnext"

v3.4

readonlyArray

Read only array

function foo(arr: ReadonlyArray<string>) {
  arr.slice(); // okay
  arr.push("hello!"); // error!
}

readonly T[]

Same effect as readonlyArray

function foo(arr: readonly string[]) {
  arr.slice(); // okay
  arr.push("hello!"); // error!
}

readonly Yuanzu

function foo(pair: readonly [string, string]) {
  console.log(pair[0]); // okay
  pair[1] = "hello!"; // error
}

const assertion

After using const assertion, the inferred types are "immutable"

// Type '"hello'", the value of x cannot be modified
let x = "hello" as const;
// Type 'readonly [10, 20]'
let y = [10, 20] as const;
// Type '{ readonly text: "hello" }'
let z = { text: "hello" } as const;

You can also write assertions using cusps:

// Type '"hello"'
let x = <const>"hello";
// Type 'readonly [10, 20]'
let y = <const>[10, 20];
// Type '{ readonly text: "hello" }'
let z = <const>{ text: "hello" };

Note that const assertions can only be applied immediately to simple literal expressions.

// Error! A 'const' assertion can only be applied to a
// to a string, number, boolean, array, or object literal.
let a = (Math.random() < 0.5 ? 0 : 1) as const;
let b = (60 * 60 * 1000) as const;
// Works!
let c = Math.random() < 0.5 ? (0 as const) : (1 as const);
let d = 3_600_000 as const;

v3.2

bigint type

bigint is part of ECMAScript's upcoming proposal

let foo: bigint = BigInt(100); // the BigInt function
let bar: bigint = 100n; // a BigInt literal

v3.1

typesVersions

A project supports multiple declaration files. For example, if the following version is greater than 3.1, go to the "ts3.1" folder under the project to find the declaration file

// tsconfig.js
{
    "typesVersions": {
        ">=3.1": { "*": ["ts3.1/*"] }
        ">=3.2": { "*": ["ts3.2/*"] }
    }
}

v2.9

import type

New -- declarationMap

With -- Declaration enabled together with -- Declaration map, the compiler is generating d. TS will be generated at the same time d.ts.map. Language services can now understand these map files and map the declaration files to the source code.

In other words, generated after -- declarationMap is enabled d. Clicking go to definition in the TS file will navigate to the location (. TS) in the source file instead of the. d.ts file.

v2.8

-/+

Yes, readonly /? Modifier to control addition and deletion

type MutableRequired<T> = { -readonly [P in keyof T]-?: T[P] }; // Remove readonly and?
type ReadonlyPartial<T> = { +readonly [P in keyof T]+?: T[P] }; // Add readonly and?

v2.7

let x!: number[];

Initializing variables directly asserts that they have been assigned

// Without this!, It will prompt "operation cannot be performed before assignment"
let x!: number[];
// The assignment ts of this function is undetectable, so "!" is used in the previous line
initialize();
x.push(4);

function initialize() {
  x = [0, 1, 2, 3];
}

v2.6

Chinese tsc

tsc --locale zh-cn

The following command line prompts will be displayed in Chinese

@ts-ignore

@The TS ignore comment hides the next line of error

if (false) {
  // @TS ignore: error in code that cannot be executed
  console.log("hello");
}

v2.5

You can omit parameters in try/catch

let input = "...";
try {
  JSON.parse(input);
} catch {
  // ^Note that our 'catch' statement does not declare a variable
  console.log("Incoming JSON wrongful\n\n" + input);
}

v2.4

For dynamic import, many packaging tools already support import asynchronous loading modules

Note: you need to set the target module in tsconfig to "esnext"

async function getZipFile(name: string, files: File[]): Promise<File> {
  const zipUtil = await import("./utils/create-zip-file");
  const zipContents = await zipUtil.getContentAsBlob(files);
  return new File(zipContents, name);
}

v2.3

@ts-nocheck

Declare that the file does not detect the type through the "/ / @ TS nocheck" annotation

// @ts-nocheck
let a;
// It should have indicated that a was not assigned
a.push(123);

v2.0

Quick external module declaration

When you use a new module, if you don't want to spend time writing a declaration, now you can use the shortcut declaration to get started quickly.

// xxx.d.ts
declare module "hot-new-module";

All imports are of type any

// x. Y is any
import x, { y } from "hot-new-module";
x(y);

Wildcards in module names

This vue initializes the project, which is used to declare A vue file is a component

declare module "*.vue" {
  import { DefineComponent } from "vue";
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
  const component: DefineComponent<{}, {}, any>;
  export default component;
}

also:

declare module "*!text" {
  const content: string;
  export default content;
}
// Some do it the other way around.
declare module "json!*" {
  const value: any;
  export default value;
}

Wechat group

Thank you for reading. If you have any questions, you can add me wechat and I'll pull you into the wechat group (because Tencent has a limit of 100 people on the wechat group, more than 100 people must be pulled in by the group members)

github

My personal open source is based on ts, welcome to visit https://github.com/any86

Keywords: Javascript Front-end TypeScript

Added by johnsiilver on Mon, 13 Dec 2021 03:05:05 +0200