Skip to content
本页目录

类型

原始数据类型

1. Number 数值

TS
let age: number = 16
let age: number = 16

2. String 字符串

TS
let name: string = 'Tom'
let name: string = 'Tom'

3. Boolean 布尔

TS
let isMale: boolean = true
let isMale: boolean = true

4. Null

TS
let u: undefined = undefined
let u: undefined = undefined

5. Undefined

TS
let u: undefined = undefined
let u: undefined = undefined

引用数据类型

1. Array 数组

1.1 基础表示法

TS
let arr: number[] = [1, 2, 3]
let arr: number[] = [1, 2, 3]

1.2 数组泛型

TS
let arr: Array<number> = [1, 2, 3] // 数组泛型
let arr: Array<number> = [1, 2, 3] // 数组泛型

1.3 类数组

  1. 数组描述
TS
function sum: void() {
  let args = {
    [index: number]: number;
    length: number;
    callee: Function;
  } = arguments;
}
function sum: void() {
  let args = {
    [index: number]: number;
    length: number;
    callee: Function;
  } = arguments;
}
  1. 接口定义
TS
interface IArguments = {
  [index: number]: number;
  length: number;
  callee: Function;
}

function sum: void() {
  let args: IArguments = arguments;
}
interface IArguments = {
  [index: number]: number;
  length: number;
  callee: Function;
}

function sum: void() {
  let args: IArguments = arguments;
}

常用的类数组都有内置的接口定义,如 IArguments, NodeList, HtmlCollection

1.4 数组 any

TS
let list: any[] = [1, 'a', {b: 2}];
let list: any[] = [1, 'a', {b: 2}];

2. Object 对象

  • 对象使用 interface 定义类型,一般接口名称前添加 I 前缀;
  • 对象的属性需要与接口定义的属性一一对应,可选、任意属性除外;
  • interface 的字段结尾使用 ;

基本用法

TS
function create(o: object | null): void {

}
function create(o: object | null): void {

}

接口定义

TS
interface IPerson {
  readonly id: number; // readonly 只读属性,对象被赋值时该字段必须赋值,被赋值后该字段不可修改
  name: string;
  gender?: string;  // ?: 表示可选属性
  [propName: string]: any;  // 任意属性,确定属性和可选属性的类型必须是它的类型的子集
}

let tom: IPerson = {
  id: 1,
  name: "Tom",
  age: 18
}
interface IPerson {
  readonly id: number; // readonly 只读属性,对象被赋值时该字段必须赋值,被赋值后该字段不可修改
  name: string;
  gender?: string;  // ?: 表示可选属性
  [propName: string]: any;  // 任意属性,确定属性和可选属性的类型必须是它的类型的子集
}

let tom: IPerson = {
  id: 1,
  name: "Tom",
  age: 18
}

3. Function 函数

3.1 函数声明

TS
function sum(x: number, y: number): number {
  return x + y;
}

sum(1, 2);
function sum(x: number, y: number): number {
  return x + y;
}

sum(1, 2);

3.2 函数表达式

日常写法

TS
let sum = function(x: number, y: number): number {
  return x + y;
}
let sum = function(x: number, y: number): number {
  return x + y;
}

完整写法

TS
// 注意第一个 => 是表示函数定义,左边是输入类型,右边是输出类型,而不是 ES6 的箭头函数
let sum: (x: number, y: number) => number = function(x: number, y: number): number {
  return x + y;
}
// 注意第一个 => 是表示函数定义,左边是输入类型,右边是输出类型,而不是 ES6 的箭头函数
let sum: (x: number, y: number) => number = function(x: number, y: number): number {
  return x + y;
}

3.3 可选参数、默认值与剩余参数

TS
// 可选参数
function sum(x: number, y?: number) {
  if(y) {
    return x + y;
  } else {
    return x;
  }
}

// 默认值
function sum(x: number, y: number = 10) {
  return x + y;
}

// 剩余参数
function sum(x: number, ...args: any[]) {

}
// 可选参数
function sum(x: number, y?: number) {
  if(y) {
    return x + y;
  } else {
    return x;
  }
}

// 默认值
function sum(x: number, y: number = 10) {
  return x + y;
}

// 剩余参数
function sum(x: number, ...args: any[]) {

}

3.4 重载

当函数接收不同数量或类型的参数时,作出不同的处理

TS
// 函数定义
function reverse(x: number): number;
function reverse(x: string): string;

// 函数实现
function reverse(x: number | string): number | string | void {
  if (typeof x === 'number') {
    return Number(x.toString().split('').reverse().join(''));
  } else if (typeof x === 'string') {
    return x.split('').reverse().join('');
  }
}
// 函数定义
function reverse(x: number): number;
function reverse(x: string): string;

// 函数实现
function reverse(x: number | string): number | string | void {
  if (typeof x === 'number') {
    return Number(x.toString().split('').reverse().join(''));
  } else if (typeof x === 'string') {
    return x.split('').reverse().join('');
  }
}

其它数据类型

1. Void 无类型

一般用于无返回值的函数

TS
function fn(): void {

}
function fn(): void {

}

2. Any 任意类型

  • 顶级类型,不会被类型检查
  • 变量声明未指定类型,则被识别为任意值类型
  • 声明一个变量为任意值之后,对它的任何操作,返回的内容的类型都是任意值
TS
let u: any = 'a'
let u: any = 'a'

3. Unknown

顶级类型,用于取代 any 的缺点,注意其与 any 的区别

TS
let some: unknown = 6
let some: unknown = 6

4. Never

5. Emun 枚举类型

  1. 数字枚举:
TS
enum Gender {
  Male,
  Female,
}

let tom: Gender = Gender.Male; // 0
enum Gender {
  Male,
  Female,
}

let tom: Gender = Gender.Male; // 0
  1. 字符串枚举
TS
enum Gender {
  Male = "Male",
  Female = "Female",
}

let tom: Gender = Gender.Male; // Male
enum Gender {
  Male = "Male",
  Female = "Female",
}

let tom: Gender = Gender.Male; // Male
  1. 异构枚举
TS
enum Enum {
  A,
  B = "B",
  C = 8,
}

Enum.A  // 0
Enum.B  // "B"
enum Enum {
  A,
  B = "B",
  C = 8,
}

Enum.A  // 0
Enum.B  // "B"

6. Tuple 元组类型

简单来说元组类型用于定义拥有不同类型元素的数组

TS
let tom: [string, number] = ['Tom', 18];
let tom: [string, number] = ['Tom', 18];

进阶

1. 类型推论

  1. 如果变量第一次赋值时没有指定类型,会根据第一次赋值的类型进行推论,后续不能赋予其它类型的值
TS
let foo = 'Tom'; // 等价于 let foo: string = 'Tom'
foo = 1;  // 报错 Type 'number' is not assignable to type 'string'
let foo = 'Tom'; // 等价于 let foo: string = 'Tom'
foo = 1;  // 报错 Type 'number' is not assignable to type 'string'
  1. 如果变量定义时没有赋值,则会被推断为 any 类型,后续可以被任意赋值
TS
let foo;
foo = 'Tom';
foo = 7;
let foo;
foo = 'Tom';
foo = 7;

2. 联合类型

TS
let foo: string | number;
let foo: string | number;

注意:

  1. 只能访问联合类型变量的共有属性或方法
TS
function getString(something: string | number): string {
  return something.toString(); // 只能使用 string 与 number 的共有方法
}
function getString(something: string | number): string {
  return something.toString(); // 只能使用 string 与 number 的共有方法
}
  1. 联合类型变量被赋值后,会根据类型推论的规则推断出一个类型
TS
let foo: string | number;
foo = 'Tom';
foo.length; // 3
foo.toFixed(2); // 报错
let foo: string | number;
foo = 'Tom';
foo.length; // 3
foo.toFixed(2); // 报错

1. Type 类型别名

类型别名,用于给类型定义新的名字,一般用于联合类型中

TS
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
  if (typeof n === 'string') {
      return n;
  } else {
      return n();
  }
}
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
  if (typeof n === 'string') {
      return n;
  } else {
      return n();
  }
}

2. 字符串字面量类型

用来约束取值只能是某几个字符串中的一个

JS
// 使用 type 定义字符串字面量类型 EventNames,它只能取三种字符串中的一种
type EventNames = 'click' | 'scroll' | 'mousemove';

function handleEvent(ele: Element, event: EventNames) {
  // do something
}

handleEvent(document.querySelector('#hello'), 'scroll');  // 没问题
// 使用 type 定义字符串字面量类型 EventNames,它只能取三种字符串中的一种
type EventNames = 'click' | 'scroll' | 'mousemove';

function handleEvent(ele: Element, event: EventNames) {
  // do something
}

handleEvent(document.querySelector('#hello'), 'scroll');  // 没问题

3. 类型断言

手动指定一个值的类型

  1. as 类型(推荐用法)
TS
  1. <类型> 值

泛型

泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性

1. 基本用法

TS
function createArray<T>(length: number, value: T): Array<T> {
  let arr: T[] = [];
  for(let i: number = 0; i < length; i++) {
    arr.push(value);
  }
  return arr;
}

createArray<string>(3, 'a');
function createArray<T>(length: number, value: T): Array<T> {
  let arr: T[] = [];
  for(let i: number = 0; i < length; i++) {
    arr.push(value);
  }
  return arr;
}

createArray<string>(3, 'a');

2. 多参数

TS
// 输入数组元素位置交换
function swap<T, U>(arr: [T, U]): [U, T] {
  return [arr[1], arr[0]];
}

swap([1, 'a']);
// 输入数组元素位置交换
function swap<T, U>(arr: [T, U]): [U, T] {
  return [arr[1], arr[0]];
}

swap([1, 'a']);

3. 泛型接口

TS
interface ICreateArray {
  <T>(length: number, value: T): Array<T>;
}

let createArray: ICreateArray = function<T>(length: number, value: T): Array<T> {
    let result: T[] = [];
    for (let i = 0; i < length; i++) {
        result[i] = value;
    }
    return result;
}
createArray(3, 'x'); // ['x', 'x', 'x']
interface ICreateArray {
  <T>(length: number, value: T): Array<T>;
}

let createArray: ICreateArray = function<T>(length: number, value: T): Array<T> {
    let result: T[] = [];
    for (let i = 0; i < length; i++) {
        result[i] = value;
    }
    return result;
}
createArray(3, 'x'); // ['x', 'x', 'x']

将泛型参数提到接口上

TS
interface CreateArrayFunc<T> {
  (length: number, value: T): Array<T>;
}

let createArray: CreateArrayFunc<any>;
createArray = function<T>(length: number, value: T): Array<T> {
  let result: T[] = [];
  for (let i = 0; i < length; i++) {
      result[i] = value;
  }
  return result;
}

createArray(3, 'x'); // ['x', 'x', 'x']
interface CreateArrayFunc<T> {
  (length: number, value: T): Array<T>;
}

let createArray: CreateArrayFunc<any>;
createArray = function<T>(length: number, value: T): Array<T> {
  let result: T[] = [];
  for (let i = 0; i < length; i++) {
      result[i] = value;
  }
  return result;
}

createArray(3, 'x'); // ['x', 'x', 'x']

4. 泛类型

TS
class GenericNumber<T> {
  initValue: T;
  add: (x: T, y: T) => T;
}

let genericNumber = new GenericNumber<number>();
genericNumber.zeroValue = 0;
genericNumber.add = function(x, y) { return x + y; };
class GenericNumber<T> {
  initValue: T;
  add: (x: T, y: T) => T;
}

let genericNumber = new GenericNumber<number>();
genericNumber.zeroValue = 0;
genericNumber.add = function(x, y) { return x + y; };

5. 默认参数

TS
function createArray<T = string>(length: number, value: T): Array<T> {
  let result: T[] = [];
  for (let i = 0; i < length; i++) {
      result[i] = value;
  }
  return result;
}
function createArray<T = string>(length: number, value: T): Array<T> {
  let result: T[] = [];
  for (let i = 0; i < length; i++) {
      result[i] = value;
  }
  return result;
}

内置对象

ES 内置对象

TS
let e: Error = new Error('Error');
let d: Date = new Date();
let b: Boolean = new Boolean(1);
// 其它
let e: Error = new Error('Error');
let d: Date = new Date();
let b: Boolean = new Boolean(1);
// 其它

DOM / BOM 内置对象

DocumentHTMLElementEventNodeList 等。

TS
let body: HTMLElement = document.body;
let allDiv: NodeList = document.querySelectorAll('div');

document.addEventListener('click', function(e: MouseEvent) {
  // Do something
});
let body: HTMLElement = document.body;
let allDiv: NodeList = document.querySelectorAll('div');

document.addEventListener('click', function(e: MouseEvent) {
  // Do something
});

声明合并

定义多个相同名字的函数、接口或类,会被合并为一个类型

1. 函数合并

即函数重载

2. 接口合并

  • 不同属性合并
  • 相同属性且类型一致会覆盖,类型不一致会报错
  • 相同名称的方法与函数合并一致,都会保留,即函数重载
TS
interface IPerson {
  name: string;
  run(speed: number): number;
}

interface IPerson {
  age: number;
  run(speed: number, time: number): number;
}
interface IPerson {
  name: string;
  run(speed: number): number;
}

interface IPerson {
  age: number;
  run(speed: number, time: number): number;
}

等同于:

TS
interface IPerson {
  name: string;
  age: number;
  run(speed: number): number;
  run(speed: number, time: number): number;
}
interface IPerson {
  name: string;
  age: number;
  run(speed: number): number;
  run(speed: number, time: number): number;
}

3. 类合并

与接口合并一致