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