Personal learning is given priority to and conveniently for others. 😉

Initial address: github.com/any86/ts-lo… This article will be updated continuously.

🔥 Reading Instructions

Due to personal limitations, this article filters only the type/syntax information from the typescript update log. Prior to version 3.1, it was just the basics, so it was only a partial selection. If there are mistakes, please give advice and help.

Note: type inference changes (relaxed/narrowed) and configuration items as well as new syntax selections for ECMA.

v4.5

New Await type

Gets the type of Prmoise’s resolve value

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

// Type parameters are not Promise types,
// Then no processing, return directly
type S = Awaited<string>; // string
Copy the code

Import the name modifier “type”

The syntax “import type {xx} from ‘XXX ‘” was supported in previous versions, and now supports the “type” tag for individual imports.

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

Check that private attributes of the class exist

Synchronously compatible with ECMA syntax

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

Import the assertion

Synchronization compatible with ECMA syntax, the import file for runtime judgment, TS does not do any judgment.

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

There is also the syntax for the “import” function:

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

v4.4

Type protection is smarter

Common types of protection are as follows:

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

If typeof input === ‘number’ was abstracted into a variable, type protection was disabled prior to version 4.4, but ts was properly type protected in version 4.4.

function nOrs() {
  return Math.random() > 0.5 ? 123 : "abc";
}
const input = nOrs();
const isNumber = typeof input === "number";
if (isNumber) {
  // Input is of type number
  input++;
}
Copy the code

Note: Required to be protected must be “const variables “or” properties of realdOnly “, such as the input above and the “n” property 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;
}
Copy the code

Type protection goes further

You can narrow down the range of union types by attribute determination.

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; }}Copy the code

⚡ added a key that supports symbol as an object type

Before only supports the “string | number”, describes the key cause for the Object type is not comprehensive, solve now.

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

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

Class static block

Sync supports es new syntax

class Foo {
  static #count = 0;

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

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

v4.3

The override keyword

“Override” is the syntax provided to a class to flag whether an attribute/method in a subclass overrides an attribute/method of the same name in the parent class.

class A {}

class B extends A {
  Override cannot be used because there is no "A" field in the base class.
  override a(){}}Copy the code

@link in the 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
}
Copy the code

v4.2

The primitive supports optional symbols

let c: [string.string? ] = ["hello"];
c = ["hello"."world"];
Copy the code

Meta-ancestor type definitions support the use of “…” anywhere.

But it requires that there be no optional elements at the end. 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];
Copy the code

The wrong sample

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.
Copy the code

v4.1

Template string type

The syntax is the same as in ES6, except that it wraps 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`;
Copy the code

New string type

New Uppercase/Lowercase/Capitalize/Uncapitalize types for TS

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

As is used in the key IN structure

You get the key, you get the value, but you don’t get the key, you just get the value, and then you re-annotate 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"} >.Copy the code

v4.0

The rest terms of primitives can be precisely deduced

Used to get the type of a tuple except for 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[]]
Copy the code

Rest elements can appear anywhere in a tuple, not just at the end!

Here we ask “…” The following elements must be tuples, 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[]];Copy the code

Tuple elements can be tagged

The main purpose is to be compatible with the definition of function parameters, because function parameters have parameter names.

type Range = [start: number.end: number];
Copy the code

Assignment of the constructor in class directly leads to the type of the property

When defining attributes, you can omit the type annotation.

class A {
  // a is of type number
  // Type can be omitted, a cannot be omitted
  a;
  constructor() {
    this.a = 1; }}Copy the code

The catch argument in try/catch becomes unknown

Judgment or assertion is required before use.

try {
  // ...
} catch (e) {
  e; // unknown
}
Copy the code

/*_ @deprecated _/

Flag deprecation.

v3.9

// @ts-expect-error

Unlike the “// @ts-ignore” motivation, “// @ts-expect-error” is mainly used when you make errors on purpose, such as test cases.

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

// You want to test the incoming numeric 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();
Copy the code

v3.8

import type / export type

New syntax added for type-only imports and exports.

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

Class private property “#”

Syncing ECMA’s private property syntax, unlike private modifiers, private properties after # are not accessible outside the class even after being js.

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

export * as ns

Export syntax, syncing with ecma2020 syntax

export * as utilities from "./utilities.js";
Copy the code

The await keyword of the top-level scope

Ecma syntactic, must be used within modules, so at least one “empty export (})”

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

Another restriction is the configuration item: “target” is ES2017 above and “module” is “ESNext”

v3.4

readonlyArray

A read-only array

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

readonly T[]

Has the same effect as readonlyArray.

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

Readonly tuples

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

Const assertion

Using const assertions, inferred types are “unmodifiable”.

// Type '"hello"', cannot change the value of x
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;
Copy the code

You can also write using sharp horn assertions:

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

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;
Copy the code

v3.2

Bigint type

Bigint is part of an upcoming ECMAScript proposal.

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

v3.1

typesVersions

A project supports multiple declaration files. For example, if the following version is larger 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 / *"]}}}Copy the code

v2.9

The import type

New – declarationMap

With –declaration enabled –declarationMap, the compiler generates.d.ts as well as.d.ts. The language service can now also understand these map files and map the declaration files to the source code.

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

v2.8

-/+

The readonly /? Modifier to add or delete control.

type MutableRequired<T> = { -readonly [P inkeyof T]-? : T[P] };// Remove readonly and?
type ReadonlyPartial<T> = { +readonly [P inkeyof T]+? : T[P] };// Add readonly and?
Copy the code

v2.7

let x! : number[];

The initialization variable directly asserts that the value is assigned.

// There is no such thing! "Can't operate until assignment."
letx! :number[];
// The assignment to this function is not detectable, so the previous line uses "!"
initialize();
x.push(4);

function initialize() {
  x = [0.1.2.3];
}
Copy the code

v2.6

Chinese TSC

tsc --locale zh-cn
Copy the code

The following command line prompts are displayed in Chinese.

@ts-ignore

The @ts-ignore comment hides the next line of errors

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

v2.5

Catch can omit arguments in try/catch

let input = "...";
try {
  JSON.parse(input);
} catch {
  // ^ Notice that our 'catch' statement does not declare a variable
  console.log("Invalid JSON \n\n" + input);
}
Copy the code

v2.4

Dynamic import. Many packaging tools already support asynchronous import loading of 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);
}
Copy the code

v2.3

@ts-nocheck

Declare that the file does not detect types with the “// @ts-nocheck” comment.

// @ts-nocheck
let a;
// A should have been left unassigned.
a.push(123);
Copy the code

v2.0

Quick external module declaration

If you don’t want to spend time writing a declaration when using a new module, you can now use shortcut declarations to get a quick start.

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

All imports are of type any

// x and y are any
import x, { y } from "hot-new-module";
x(y);
Copy the code

The wildcard character in the module name

This is in the vUE initialization project, which declares that the.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;
}
Copy the code

There are:

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;
}
Copy the code

WeChat group

Thank you for your reading. If you have any questions, you can add me to the wechat group, and I will pull you into the wechat group (Because Tencent limits the number of wechat groups to 100, when the number exceeds 100, you must be joined by group members).

github

My own open source is based on TS, please visit github.com/any86