CD's blog CD's blog
首页
  • HTMLCSS
  • JavaScript
  • Vue
  • TypeScript
  • React
  • Node
  • Webpack
  • Git
  • Nestjs
  • 小程序
  • 浏览器网络
  • 学习笔记

    • 《TypeScript 从零实现 axios》
    • Webpack笔记
  • JS/TS教程

    • 《现代JavaScript》教程
🔧工具方法
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

CD_wOw

内卷的行情,到不了的梦
首页
  • HTMLCSS
  • JavaScript
  • Vue
  • TypeScript
  • React
  • Node
  • Webpack
  • Git
  • Nestjs
  • 小程序
  • 浏览器网络
  • 学习笔记

    • 《TypeScript 从零实现 axios》
    • Webpack笔记
  • JS/TS教程

    • 《现代JavaScript》教程
🔧工具方法
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • TypeScript类型梳理
    • 简单基础类型
    • 复杂基础类型
      • 数组
      • 元组
    • 特殊类型
      • any
      • unknown
      • void、undefined、null
      • never
    • 字面量类型
    • 返回值类型
    • 类型拓宽
    • 类型缩小
    • 类型断言
    • 函数重载
    • 类型谓词(is)
    • Ts 工具类型
      • 函数类型
      • 字符串类型
      • 对象的类型
      • 函数的类型注解
    • 接口
    • ES6 class 类中应用 TS
      • class 类的修饰器
      • class 类的构造函数中使用类型校验
      • class 类的 getter、setter 和 static
      • class 类的只读属性
      • 抽象类
    • 配置文件 tsconfig.json
  • TypeScript联合、交叉类型解读
  • TypeScript枚举用法解读
  • keyof用法梳理
  • extends用法梳理
  • type-challenges笔记
  • TypeScript笔记
CD_wOw
2021-08-01
目录

TypeScript类型梳理

在编译(转译)时期,TypeScript 编译器将通过对比检测变量接收值的类型与我们显示注解的类型,从而检测类型是否存在错误。如果两个类型完全一致,显示检测通过;如果两个类型不一致,它就会抛出一个编译期错误,告知我们编码错误

# 简单基础类型

基础类型在 ts 中有大小写的分别,如 String 和 string。可以自我思考一下 new String(xxx) 和 string = xxx 两者的区别从而为你的变量定义类型

  1. string
  2. number (ts 中还有 bigint)
  3. boolean
  4. symbol
  5. null
  6. undefined

(null 是一个伪原始类型,它在 JavaScript 中实际上是一个对象,且所有的结构化类型都是通过 null 原型链派生而来)

# 复杂基础类型

# 数组

TypeScript 的数组和元组转译为 JavaScript 后都是数组,定义数组有两种方式:

  1. 直接使用 type[]的形式定义
  2. 使用 Array 泛型
let numberArr: Array<number> = [1, 2, 3];
let numberArr: number[] = [1, 2, 3];
1
2

更加推荐使用[]的方式来定义数组,可以避免与 JSX 的语法冲突以及更少的代码量,缺点是在对应空数组时就会报错。

# 元组

元组最重要的特性是可以限制数组元素的个数和类型,它特别适合用来实现多值返回。

const require: [data:string, code: number] = [data, code]
1

# 特殊类型

# any

any 指的是一个任意类型,它是官方提供的一个选择性绕过静态类型检测的作弊方式。我们可以对被注解为 any 类型的变量进行任何操作,包括获取事实上并不存在的属性、方法,并且 TypeScript 还无法检测其属性是否存在、类型是否正确。我们可以把 any 类型的值赋值给任意类型(除 never 以外)的变量

let anything: any = "ww";
anything = 123; //不会报错
1
2

# unknown

unknown 用来描述类型并不确定的变量。在 ts3.0 之前,对接收未知值的类型我们通常只能使用 any 来定义,3.0 之后我们可以将可以获取任意值的变量赋予 unknown 属性

# void、undefined、null

  1. void: 函数返回空值时做的定义
  2. undefined: 没什么用,表示一个可缺省、未定义的属性。
  3. null:作用也不大,一般用在接口返回空对象等地方。

(我们可以把 undefined 值或类型是 undefined 的变量赋值给 void 类型变量,反过来,类型是 void 但值是 undefined 的变量不能赋值给 undefined 类型)

undefined 在 tsconfig strictNullChecks 为 true 的情况下是 void 和 any 类型子类型,为 false 的情况下则是除了 never 的子类型

# never

never 表示永远不会发生值的类型,是所有类型的子类型,可以给所有的类型赋值,但是除自身以外的类型不能为其赋值

const neverType: never = "never";
neverType = 123; // ts(2322))
const otherStr: string = neverType; // 通过
const otherInt: number = neverType; // 通过
const props: {
  id: number,

  name?: never,
} = {
  id: 1,
};

props.name = null; // ts(2322))

props.name = "str"; // ts(2322)

props.name = 1; // ts(2322)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

这里我们无论给 name 赋什么值,都会报类型错误,never 类型的变量也不能接受其他类型值

# 字面量类型

在 TypeScript 中,字面量不仅可以表示值,还可以表示类型,即所谓的字面量类型。

目前,TypeScript 支持 3 种字面量类型:字符串字面量类型、数字字面量类型、布尔字面量类型,对应的字符串字面量、数字字面量、布尔字面量分别拥有与其值一样的字面量类型,具体示例如下:

{
  let specifiedStr: "this is string" = "this is string";

  let specifiedNum: 1 = 1;

  let specifiedBoolean: true = true;
}
1
2
3
4
5
6
7

字面量类型是集合类型的子类型,它是集合类型的一种更具体的表达。比如 'this is string' (这里表示一个字符串字面量类型)类型是 string 类型(确切地说是 string 类型的子类型),而 string 类型不一定是 'this is string'(这里表示一个字符串字面量类型)类型

{
  let specifiedStr: "this is string" = "this is string";

  let str: string = "any string";

  specifiedStr = str; // ts(2322) 类型 '"string"' 不能赋值给类型 'this is string'

  str = specifiedStr; // ok
}
1
2
3
4
5
6
7
8
9

比如说我们用“马”比喻 string 类型,即“黑马”代指 'this is string' 类型,“黑马”肯定是“马”,但“马”不一定是“黑马”,它可能还是“白马”“灰马”。因此,'this is string' 字面量类型可以给 string 类型赋值,但是 string 类型不能给 'this is string' 字面量类型赋值,这个比喻同样适合于形容数字、布尔等其他字面量和它们父类的关系。

# 返回值类型

在 JavaScript 中,我们知道一个函数可以没有显式 return,此时函数的返回值应该是 undefined, 如果我们显式声明函数的返回值类型为 undfined,将会得到如下所示的错误提醒。

function fn() {
  // TODO
}

console.log(fn()); // => undefined

function fn(): undefined {
  // ts(2355) A function whose declared type is neither 'void' nor 'any' must return a value
  // TODO
}
1
2
3
4
5
6
7
8
9
10

当没有返回值时函数正确的赋值方式应该是 void。由于函数返回值的类型可以在 TypeScript 中被推断出来,即可缺省,通常我们可以不用专门定义,但是有些特例需要我们显式声明返回值类型,比如 Generator 函数的返回值。

ES6 中新增的 Generator 函数在 TypeScript 中也有对应的类型定义。

Generator 函数返回的是一个 Iterator 迭代器对象,我们可以使用 Generator 的同名接口泛型或者 Iterator 的同名接口泛型表示返回值的类型(Generator 类型继承了 Iterator 类型),示例如下:

type AnyType = boolean;

type AnyReturnType = string;

type AnyNextType = number;

function* gen(): Generator<AnyType, AnyReturnType, AnyNextType> {
  const nextValue = yield true; // nextValue 类型是 number,yield 后必须是 boolean 类型

  return `${nextValue}`; // 必须返回 string 类型
}
1
2
3
4
5
6
7
8
9
10
11

# 类型拓宽

比如对 null 和 undefined 的类型进行拓宽,通过 let、var 定义的变量如果满足未显式声明类型注解且被赋予了 null 或 undefined 值,则推断出这些变量的类型是 any:

{
  let x = null; // let定义的变量类型拓宽成 any

  let y = undefined; // let定义的变量类型拓宽成 any

  /** -----分界线------- */

  const z = null; // 类型是 null

  /** -----分界线------- */

  let anyFun = (param = null) => param; // 形参类型是 null

  let z2 = z; // 类型是 null

  let x2 = x; // 类型是 null

  let y2 = y; // 类型是 undefined

  //TIPS: 在严格模式下,一些比较老的版本中(2.0)null 和 undefined 并不会被拓宽成“any”
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 类型缩小

在 TypeScript 中,我们可以通过某些操作将变量的类型由一个较为宽泛的集合缩小到相对较小、较明确的集合.例如我们采用 if 判断将原本处于 number|string 类型的变量缩小为其中一个子类型,当然不止限于 if,还有三目运算符、switch 等等约束条件都能产生同样的效果

# 类型断言

类型断言是对类型的强制转化,让 ts 接受它的类型选择 例如:

const nums: number[] = [1, 2, 3, 4, 5];
const bigNumber: number = nums.find((i) => i > 2); // 由于 find方法会返回number | undefined 类型,此时定义的bigNumber只能是number类型,这个时候就会出现类型错误

// 通过as (type) 的方式让ts默认认为返回的就是一个number类型的参数
const bigNumber: number = nums.find((i) => i > 2) as number;
// 尖括号也行,但是会和jsx语法产生冲突
const bigNumber: number = \<number>nums.find((i) => i > 2);
1
2
3
4
5
6
7

# 函数重载

JavaScript 是一门动态语言,针对同一个函数,它可以有多种不同类型的参数与返回值,这就是函数的多态。

而在 TypeScript 中,也可以相应地表达不同类型的参数和返回值的函数

function convert(x: string | number | null): string | number | -1 {
  if (typeof x === "string") {
    return Number(x);
  }

  if (typeof x === "number") {
    return String(x);
  }

  return -1;
}

const x1 = convert("1"); // => string | number

const x2 = convert(1); // => string | number

const x3 = convert(null); // => string | number
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

我们把 convert 函数的 string 类型的值转换为 number 类型,number 类型转换为 string 类型,而将 null 类型转换为数字 -1。此时, x1、x2、x3 的返回值类型都会被推断成 string | number 。

那么,有没有一种办法可以更精确地描述参数与返回值类型约束关系的函数类型呢?有,这就是函数重载(Function Overload),如下示例中 1~3 行定义了三种各不相同的函数类型列表,并描述了不同的参数类型对应不同的返回值类型,而从第 4 行开始才是函数的实现。

function convert(x: string): number;
function convert(x: number): string;
function convert(x: null): -1;
function convert(x: string | number | null): any {
  if (typeof x === "string") {
    return Number(x);
  }
  if (typeof x === "number") {
    return String(x);
  }
  return -1;
}
const x1 = convert("1"); // => number

const x2 = convert(1); // => string

const x3 = convert(null); // -1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

函数重载列表的各个成员(即示例中的 1 ~ 3 行)必须是函数实现(即示例中的第 4 行)的子集,例如 “function convert(x: string): number”是“function convert(x: string | number | null): any”的子集。

在 convert 函数被调用时,TypeScript 会从上到下查找函数重载列表中与入参类型匹配的类型,并优先使用第一个匹配的重载定义。因此,我们需要把最精确的函数重载放到前面。例如我们在第 14 行传入了字符串 '1',查找到第 1 行即匹配,而第 15 行传入了数字 1,则查找到第 2 行匹配。

我们通过以下一个示例进行具体说明

interface P1 {
  name: string;
}

interface P2 extends P1 {
  age: number;
}

function convert(x: P1): number;
function convert(x: P2): string;
function convert(x: P1 | P2): any {}
const x1 = convert({ name: "" } as P1); // => number
const x2 = convert({ name: "", age: 18 } as P2); // number
1
2
3
4
5
6
7
8
9
10
11
12
13

# 类型谓词(is)


function isString(s): s is string { // 类型谓词
  return typeof s === 'string';
}

function isNumber(n: number) {
  return typeof n === 'number';
}

function operator(x: unknown) {
  if(isString(x)) { // ok x 类型缩小为 string
  }
  if (isNumber(x)) { // ts(2345) unknown 不能赋值给 number
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

在上述代码中,在添加返回值类型的地方,我们通过“参数名 + is + 类型”的格式明确表明了参数的类型,进而引起类型缩小,所以类型谓词函数的一个重要的应用场景是实现自定义类型守卫(详见第 11 讲)。

# Ts 工具类型

  1. enum: 枚举

  2. type, interface

  3. 联合类型 | (联合类型一次只能一种类型;而交叉类型每次都是多个类型的合并类型。)

  4. 交叉类型 & (联合类型一次只能一种类型;而交叉类型每次都是多个类型的合并类型。)

  5. typeof

typeof 操作符可以用来获取一个变量声明或对象的类型。

function toArray(x: number): Array<number> {
  return [x];
}

type Func = typeof toArray; // -> (x: number) => number[]
1
2
3
4
5
  1. keyof

keyof 操作符可以用来一个对象中的所有 key 值:

interface Person {
  name: string;
  age: number;
}

type K1 = keyof Person; // "name" | "age"
1
2
3
4
5
6
  1. in

in 用来遍历枚举类型:

type Keys = "a" | "b" | "c";

type Obj = {
  [p in Keys]: any;
}; // -> { a: any, b: any, c: any }
1
2
3
4
5
  1. extends

有时候我们定义的泛型不想过于灵活或者说想继承某些类等,可以通过 extends 关键字添加泛型约束。

interface ILengthwise {
  length: number;
}

function loggingIdentity<T extends ILengthwise>(arg: T): T {
  console.log(arg.length);
  return arg;
}

loggingIdentity(3);
loggingIdentity({ length: 10, value: 3 });
1
2
3
4
5
6
7
8
9
10
11
  1. Paritial

Partial<T> 的作用就是将某个类型里的属性全部变为可选项 ?。

type Partial<T> = {
  [P in keyof T]?: T[P];
};

interface Person {
  name: string;
  age?: number;
  weight?: number;
}

type PartialPerson = Partial<Person>;

// 相当于
interface PartialPerson {
  name?: string;
  age?: number;
  weight?: number;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  1. Reuqired

Required<T> 的作用就是将某个类型里的属性全部变为必选项。

type Required<T> = {
  [P in keyof T]-?: T[P];
};

type RequiredPerson = Required<Person>;

// 相当于

interface RequiredPerson {
  name: string;
  age: number;
  weight: number;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

映射类型在键值的后面使用了一个 - 符号,- 与 ? 组合起来表示去除类型的可选属性,因此给定类型的所有属性都变为了必填。

  1. Readonly

Readonly<T> 的作用是将某个类型所有属性变为只读属性,也就意味着这些属性不能被重新赋值。

type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

type ReadonlyPerson = Readonly<Person>;

// 相当于

interface ReadonlyPerson {
  readonly name: string;
  readonly age?: number;
  readonly weight?: number;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  1. Record

Record<K extends keyof any, T> 的作用是将 K 中所有的属性的值转化为 T 类型。

interface PageInfo {
  title: string;
}

type Page = "home" | "about" | "contact";

const x: Record<Page, PageInfo> = {
  about: { title: "about" },
  contact: { title: "contact" },
  home: { title: "home" },
};
1
2
3
4
5
6
7
8
9
10
11
  1. Exclude

Exclude<T, U> 的作用是将某个类型中属于另一个的类型移除掉。

type Exclude<T, U> = T extends U ? never : T;

type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"
type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // "c"
1
2
3
4
  1. Extract

Extract<T, U> 的作用是从 T 中提取出 U。从联合类型中提取指定的类型。

type T0 = Extract<"a" | "b" | "c", "a" | "f">; // "a"
type T1 = Extract<string | number | (() => void), Function>; // () => void
1
2
  1. Pick

Pick 工具类型可以从给定的类型中选取出指定的键值,然后组成一个新的类型

interface Person {
  name: string;
  age?: number;
  weight?: number;
}

type Pick<T, K extends keyof T> = {
  [P in K]: T[P];
};

type NewPerson = Pick<Person, "name" | "age">;
// 相当于
interface NewPerson {
  name: string;
  age?: number;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  1. Omit

与 Pick 类型相反,Omit 工具类型的功能是返回去除指定的键值之后返回的新类型

interface Person {
  name: string;
  age?: number;
  weight?: number;
}

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

type NewPerson = Omit<Person, "weight">;

// 相当于
interface NewPerson {
  name: string;
  age?: number;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  1. NonNullable

从联合类型中去除 null 或者 undefined 的类型。

type NonNullable<T> = T extends null | undefined ? never : T;

// 等同于使用 Exclude

type NonNullable<T> = Exclude<T, null | undefined>;

type T = NonNullable<string | number | undefined | null>; // => string | number
1
2
3
4
5
6
7
  1. Equal

判断两个类型是否相等, 当前社区上主要有两种方案。 参考 issue (opens new window) 第一种:

export type Equal1<T, S> = [T] extends [S]
  ? [S] extends [T]
    ? true
    : false
  : false;
1
2
3
4
5

目前该方案的唯一缺点是会将 any 类型与其它任何类型判为相等。

type T = Equal1<{ x: any }, { x: number }>; // T: true
1

第二种:

export type Equal2<X, Y> = (<T>() => T extends X ? 1 : 2) extends <
  U
>() => U extends Y ? 1 : 2
  ? true
  : false;
1
2
3
4
5

目前该方案的唯一缺点是在对交叉类型的处理上有一点瑕疵。

type T = Equal2<{ x: 1 } & { y: 2 }, { x: 1; y: 2 }>; // false
1

# 函数类型

  1. ConstructorParameters

ConstructorParameters 可以用来获取构造函数的构造参数,而 ConstructorParameters 类型的实现则需要使用 infer 关键字推断构造参数的类型。

关于 infer 关键字,我们可以把它当成简单的模式匹配来看待。如果真实的参数类型和 infer 匹配的一致,那么就返回匹配到的这个类型。

type ConstructorParameters<T extends new (...args: any) => any> =
  T extends new (...args: infer P) => any ? P : never;

class Person {
  constructor(name: string, age?: number) {}
}

type T = ConstructorParameters<typeof Person>; // [name: string, age?: number]
// ConstructorParameters 泛型接收了一个参数,并且限制了这个参数需要实现构造函数。于是,我们通过 infer 关键字匹配了构造函数内的构造参数,并返回了这些参数。
1
2
3
4
5
6
7
8
9
  1. ThisType

ThisType 的作用是可以在对象字面量中指定 this 的类型。ThisType 不返回转换后的类型,而是通过 ThisType 的泛型参数指定 this 的类型(如果想使用这个工具类型,那么需要开启 noImplicitThis 的 TypeScript 配置)

type ObjectDescriptor<D, M> = {
  data?: D;
  methods?: M & ThisType<D & M>; // methods 中 this 的类型是 D & M
};
1
2
3
4

# 字符串类型

// 转换字符串字面量到大写字母

type Uppercase<S extends string> = intrinsic;

// 转换字符串字面量到小写字母

type Lowercase<S extends string> = intrinsic;

// 转换字符串字面量的第一个字母为大写字母

type Capitalize<S extends string> = intrinsic;

// 转换字符串字面量的第一个字母为小写字母

type Uncapitalize<S extends string> = intrinsic;

type T0 = Uppercase<"Hello">; // => 'HELLO'

type T1 = Lowercase<T0>; // => 'hello'

type T2 = Capitalize<T1>; // => 'Hello'

type T3 = Uncapitalize<T2>; // => 'hello'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 对象的类型

// 对象字面量的类型检查
const xiaojiejie: {
  name: string,
  age: number
} = {
  name: '小红',
  age: 18
}

// 标注:object
const obj:object = {}

// 使用接口
interface Person{
    name: string
    age: number
}
const xjj: Person = {
    name: 'xh',
    age: 18
}

// class类的类型检查
class Parson { }
const xiaobai: Parson = new Parson()

// 函数和返回值的类型检查
const fn: ()=> string = () => '123'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 函数的类型注解

// 函数返回值的类型注解 fn(): number {}
function getTotal2(one: number, two: number): number {
  return one + two;
}
getTotal2(1, 2);

// 无返回值: void
function sayHello(): void {
  console.log("Hello");
}

// 永远执行不玩的函数
function setTimer(): never {
  throw new Error();
  console.log(123);
}

// 参数是对象时的注解 (也可以用接口)
function add({ one, two }: { one: number, two: number }) {
  return one + two;
}

const total = add({ one: 1, two: 2 });
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 接口

接口,可以理解为对象属性的类型描述。和类型别名类似,不同的是 接口必须是一个对象,而别名可以直接是一个类型,如type Girl = string

interface Girl {
  // 接口 (理解:对象属性的类型描述)
  readonly name: string; // 只读属性 (定义之后不能再修改)
  age: number;
  waistline?: number; // 加个问号表示是可选值
  [propname: string]: any; // 表示可以有不限制属性名的属性,但属性名需要是字符串,值可以是任意类型
  say(): string; // 函数类型,返回值是string (如无返回值时是 void)。  say()也可以加入参数类型检查,如say(p:number)
}
// 和类型别名类似,不同的是 接口必须是一个对象,而别名可以直接是一个类型,如 type Girl = string

// 接口的继承
interface Teacher extends Girl {
  teach(): string;
}

const girl = {
  name: "大脚",
  age: 18,
  sex: "女",
  say() {
    return "欢迎光临";
  },
  teach() {
    return "教";
  },
};

const screenResume = ({ name, age, bust, sex }: Girl) => {
  console.log(name, age, bust, sex);
};
const getResume = ({ name, age, bust, teach }: Teacher) => {
  teach();
  console.log(name, age, bust);
};
screenResume(girl);
getResume(girl);

// 接口在class类中的使用
class xiaojjj implements Girl {
  name = "xiaojj";
  age = 18;
  bust = 98;
  sex = "女";
  say() {
    return "欢迎光临";
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

可索引的类型

interface Arr {
  [index: number]: string; // 表示通过索引访问数据时返回的类型是string
}

const myArr: Arr = ["1", "2", "3"];
const myStr: string = myArr[1];
1
2
3
4
5
6

# ES6 class 类中应用 TS

# class 类的修饰器

// 类的修饰器:
// public (公共) 允许内外部使用
// protected (受保护的) 允许在内部和继承内使用
// private (私有) 允许在内部使用,但不能在继承中使用

// 类的内部和外部,{}内属于内部,外面是外部
class Person {
   // public 内外都可以使用,可省略,不写时默认public。 protected只允许内部使用
  name: string // 这里的string注释是TS使用的
  private age: 18
  public sayHello() {
    console.log(this.name + this.age + 'say hello')
  }
}

class Teacher2 extends Person {
  public sayBye() {
    console.log(this.name + ' say bye') // protected 可以在继承中使用到
  }
}

const person = new Person();
person.name = 'test' // 在类的外部定义
console.log(person.name)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# class 类的构造函数中使用类型校验

class Person2 {
  constructor(public name: string) {
    this.name = name
  }
}

class Teacher3 extends Person2{
  constructor(public age: number) {
    super('test-name') // 这里传的值是给Person2的构造函数。即使父类没有构造函数,子类的构造函数内也要写super()
  }
}
const teacher3 = new Teacher3(18)
console.log(teacher3.name)
console.log(teacher3.age)
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# class 类的 getter、setter 和 static

class Xjj {
  constructor(private _age: number) { }
  get age() {
    return this._age - 10;
  }  // 访问器属性,以属性的形式访问age,并可以对属性进行包装
  set age(age: number) {
    this._age = age+3;
   }
}

const dj = new Xjj(28);
dj.age = 25

console.log(dj.age)


// 静态属性 static。  静态属性指不需要通过实例化,直接通过Girl.prop的方式就可以访问到属性
class Girl {
  static sayLove() {
    return 'I love you'
  }
}

// const girl = new Girl()
console.log(Girl.sayLove())

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# class 类的只读属性

// 只读属性
class Person {
  public readonly _name: string // 只读属性
  constructor(name: string) {
    this._name = name;
  }
}

const person = new Person('testName');
// person._name = '222'; // 不能修改只读属性
console.log(person._name)
1
2
3
4
5
6
7
8
9
10
11

# 抽象类

/ 抽象类
abstract class Girls {
  abstract skill(); // 注意这里只是定义抽象方法,而不具有方法的实现
}

class Waiter extends Girls{ // 继承了抽象类之后要 实现抽象类内的成员
  skill() {
    console.log('大爷1')
  }
}

class BaseTeacher extends Girls{
  skill() {
    console.log('大爷2')
  }
}

class SeniorTeacher extends Girls{
  skill() {
    console.log('大爷3')
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 配置文件 tsconfig.json

// 此文件由命令 tsc -init 生成
// 直接运行 tsc 命令就会运用此配置文件
// 选项详解:https://www.tslang.cn/docs/handbook/compiler-options.html
{
  // "include": ["demo15-1.ts"], // 要编译的指定文件,不配置此项时运行tsc默认编译全部
  // "files": ["demo15-1.ts"], // 和include类似
  // "exclude": ["demo15-3.ts"], // 要排除编译的指定文件
  "compilerOptions": {
    // 编译选项
    /* 基本选项 */
    // "incremental": true,                   /* Enable incremental compilation */
    "target": "es5" /* 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
    "module": "commonjs" /* 指定模块代码生成: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
    // "lib": [],                             /* Specify library files to be included in the compilation. */
    // "allowJs": true,                       /* Allow javascript files to be compiled. */
    // "checkJs": true,                       /* Report errors in .js files. */
    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    // "declaration": true,                   /* Generates corresponding '.d.ts' file. */
    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
    "sourceMap": true /* 源文件与输出文件的映射关系文件。Generates corresponding '.map' file. */,
    // "outFile": "./",                       /* Concatenate and emit output to single file. */
    "outDir": "./build" /* 输出的js文件目录。Redirect output structure to the directory. */,
    "rootDir": "./src" /* ts源文件目录。Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
    // "composite": true,                     /* Enable project compilation */
    // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
    // "removeComments": true,                /* 不输出注释到编译结果. */
    // "noEmit": true,                        /* Do not emit outputs. */
    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
    // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */

    /* 严格的类型检查选项 */
    "strict": true /* 启用所有严格类型检查选项。 打开此选项后,下面这些选项就不需要单独设置*/,
    // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. 为false时允许any不用特意声明。*/
    // "strictNullChecks": true,              /* Enable strict null checks. 为false时允许赋值为null*/
    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
    // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */

    /* 附加检查。Additional Checks  */
    // "noUnusedLocals": true,                /* Report errors on unused locals. 报告未使用的本地变量 */
    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */

    /* Module Resolution Options */
    // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                       /* List of folders to include type definitions from. */
    // "types": [],                           /* Type declaration files to be included in compilation. */
    // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
    // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */

    /* Source Map Options */
    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

    /* Experimental Options */
    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
编辑 (opens new window)
#TypeScript
上次更新: 2023/03/22, 15:28:00
TypeScript联合、交叉类型解读

TypeScript联合、交叉类型解读→

最近更新
01
gsap动画库学习笔记 - 持续~
06-05
02
远程组件加载方案笔记
05-03
03
小程序使用笔记
03-29
更多文章>
Theme by Vdoing | Copyright © 2020-2023 CD | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式