关于javascript:typescript更新日志🚀中文速读已更新到45-持续更新

集体学习为主, 顺便不便别人.😉

首发地址: https://github.com/any86/ts-l…, 本文内容也会继续更新.

🔥 浏览须知

因为集体能力无限, 所以本文只从”typescript 更新日志”中筛选类型/语法相干的知识点, 3.1之前的版本都是一些基础知识, 所以只摘取了局部内容. 如有谬误还请各位多多指导帮忙.

留神: 类型推断的变动(放宽/收窄)和配置项以及 ECMA 的新增语法选录.

v4.5

新增 Await 类型

获取 Prmoise 的 resolve 的值的类型

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

// 类型参数不是Promise类型,
// 那么不解决, 间接返回
type S = Awaited<string>; // string

导入名称修饰符”type”

之前版本就反对”import type {xx} from ‘xxx'”的语法, 当初提高反对对单个导入项标记”type”.

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

查看类的公有属性是否存在

同步兼容ecma语法

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

导入断言

同步兼容ecma语法, 对导入文件进行运行时判断, ts不做任何判断.

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

还有”import”函数的语法:

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

v4.4

类型爱护更智能

常见的类型爱护如下:

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

如果typeof input === 'number'形象到变量中,在 4.4 版本之前类型爱护会生效,然而在 4.4 中 ts 能够正确的类型爱护了.

function nOrs() {
  return Math.random() > 0.5 ? 123 : "abc";
}
const input = nOrs();
const isNumber = typeof input === "number";
if (isNumber) {
  // 生效,无奈晓得input是number类型
  input++;
}

留神: 要求被爱护的必须是”const 的变量”或者”realdonly 的属性”, 比方下面的 input 和上面的”n”属性.

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是number
  const r = a.n;
}

类型爱护更深刻

通过属性的判断能够放大联结类型的范畴.

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;
  }
}

⚡ 减少反对 symbol 类型做为对象类型的键

之前只反对”string | number “, 造成对 Object 类型的键的形容不全面, 当初解决了.

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

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

类中的 static 块

同步反对 es 新语法

class Foo {
  static #count = 0;

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

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

v4.3

override 关键字

“override”是给类提供的语法, 用来标记子类中的属性/办法是否笼罩父类的同名属性/办法.

class A {}

class B extends A {
  // 提醒不能用override, 因为基类中没有"a"字段.
  override a() {}
}

正文中的@link

点击跳转到指定代码.

/**
 * 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

元祖反对可选符号

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

元祖类型定义反对任意地位应用”…”

然而要求尾部不能有可选元素(?)和”…”呈现

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];

谬误示例

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

模板字符串类型

语法和 es6 中的”“”用法一样, 只不过这里用来包裹类型:

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`;

新增字符串类型

ts 零碎新增 Uppercase / Lowercase / Capitalize / Uncapitalize 类型

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

key in 构造中应用 as

获取 key 后用来获取值, 然而不必 key,只用值, 而后从新标注 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

元祖的 rest 项可精准推导

以前获取元组除了第一个元素的类型:

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 元素能够呈现在元组中的任何中央, 而不仅仅是在最初!

这里要求”…”前面的元素必须是元组, 只有最初一个元素能够是”…”+”数组”

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

元组元素反对带标签

次要是为了兼容函数参数的定义, 因为函数的参数都是有参数名的.

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

class 中构造函数的赋值能够间接推导出属性的类型

定义属性的时候, 能够省略类型标注.

class A {
  // 此时a间接被推导出是number类型
  // 类型能够省略, a不能省略
  a;
  constructor() {
    this.a = 1;
  }
}

try/catch 中的 catch 的参数变成 unknown 类型

应用之前须要进行判断或断言.

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

/*_ @deprecated _/

标注弃用.

v3.9

// @ts-expect-error

用来屏蔽谬误, 不同于”// @ts-ignore”的应用动机, “// @ts-expect-error”次要的应用场景是你成心产生错的, 比方测试用例.

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

// 你想测试传入数字参数, 然而ts会主动推断谬误, 这不是你想要的, 所以加"// @ts-expect-error"
expect(() => {
  // @ts-expect-error
  doStuff(123, 456);
}).toThrow();

v3.8

import type / export type

为仅类型导入和导出增加了新语法。

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

类的公有属性”#”

同步 ecma 的公有属性语法, 不同于 private 修饰符, #后的公有属性即使在编译成 js 后仍然不能在类的内部拜访.

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

export * as ns

导出语法, 同步于 ecma2020 的语法

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

顶级作用域的 await 关键字

同步于 ecma 的语法, 要求必须是模块内应用, 所以起码要有一个”空导出(export {})”

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

还有一个限度就是配置项: “target”为 es2017 以上且”module”为”esnext”

v3.4

readonlyArray

只读数组

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

readonly T[]

和 readonlyArray 同成果.

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

readonly 元祖

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

const 断言

应用 const 断言后, 推断出的类型都是”不可批改”的.

// Type '"hello"',不能批改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;

还能够写应用尖角号断言:

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

留神const 断言只能立刻利用于简略的文字表达式。

// 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 类型

bigint 是 ECMAScript 行将推出的提案的一部分.

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

v3.1

typesVersions

一个我的项目反对多个申明文件, 比方上面版本大于 3.1 就去我的项目下的”ts3.1″文件夹下查找申明文件.

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

v2.9

import 类型

新的–declarationMap

随着–declaration 一起启用–declarationMap,编译器在生成.d.ts 的同时还会生成.d.ts.map。 语言服务当初也可能了解这些 map 文件,将申明文件映射到源码。

换句话说,在启用了–declarationMap 后生成的.d.ts 文件里点击 go-to-definition,将会导航到源文件里的地位(.ts),而不是导航到.d.ts 文件里。

v2.8

-/+

对 readonly/?修饰符进行增删管制.

type MutableRequired<T> = { -readonly [P in keyof T]-?: T[P] }; // 移除readonly和?
type ReadonlyPartial<T> = { +readonly [P in keyof T]+?: T[P] }; // 增加readonly和?

v2.7

let x!: number[];

初始化变量间接断言已赋值.

// 没有这!, 会提醒"在赋值前不能进行操作"
let x!: number[];
// 这个函数的赋值ts是检测不到的, 所以上一行用了"!"
initialize();
x.push(4);

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

v2.6

中文 tsc

tsc --locale zh-cn

前面的命令行提醒都会以中文模式显示.

@ts-ignore

@ts-ignore 正文暗藏下一行谬误

if (false) {
  // @ts-ignore:无奈被执行的代码的谬误
  console.log("hello");
}

v2.5

try/catch 中 catch 能够省略参数

let input = "...";
try {
  JSON.parse(input);
} catch {
  // ^ 留神咱们的 `catch` 语句并没有申明一个变量
  console.log("传入的 JSON 不非法\n\n" + input);
}

v2.4

动静的 import, 很多打包工具都曾经反对 import 异步加载模块.

留神: 须要把 tsconfig 中的指标模块设置为”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

通过”// @ts-nocheck”正文来申明文件不检测类型.

// @ts-nocheck
let a;
// 本应该提醒a未赋值.
a.push(123);

v2.0

快捷内部模块申明

当你应用一个新模块时,如果不想要花费工夫书写一个申明时,当初你能够应用快捷申明以便以疾速开始。

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

所有导入都是any类型

// x,y 都是any
import x, { y } from "hot-new-module";
x(y);

模块名称中的通配符

这个 vue 初始化的我的项目中就有, 用来申明.vue 文件是个组件.

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;
}

还有:

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;
}

微信群

感激大家的浏览, 如有疑难能够加我微信, 我拉你进入微信群(因为腾讯对微信群的100人限度, 超过100人后必须由群成员拉入)

github

我集体的开源都是基于ts的, 欢送大家拜访https://github.com/any86

【腾讯云】轻量 2核2G4M,首年65元

阿里云限时活动-云数据库 RDS MySQL  1核2G配置 1.88/月 速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据