TypeScript 学习笔记2

目录

类型声明

typescript类型

断言

类型别名type

[interface 接口](#interface 接口)


类型声明

在使用javascript时,由于js是一个类型松散的语言,在进行运算、传参等操作时,并不会对类型进行校验,这就导致代码可能会产生运行时错误。

但typescript可以通过类型声明,实现对代码的静态校验,在代码运行之前规避部分报错。

typescript类型

1.boolean 布尔值

2.number 数字(包括整数、小数、二进制、八进制、十六进制、十进制)

3.string 字符串

4.Array<元素类型>、元素类型[] 数组

5.[元素1类型,元素2类型,......] 元组(元组允许表示一个已知元素数量和类型的数组)

6.enum 枚举 使用枚举可以使代码可读性更好,当把一个变量设定为枚举类型时,变量的值需要为枚举值其中之一

枚举类型:

6.1 数字枚举

数字枚举默认从0开始

TypeScript 复制代码
// 定义数字枚举
enum Direction {
  Up,    // 0
  Down,  // 1
  Left,  // 2
  Right  // 3
}

// 使用枚举
const move: Direction = Direction.Up;
console.log(move); // 输出 0
console.log(Direction.Down); // 输出 1

可以手动规定第一个枚举值,后续枚举值会依次递增

TypeScript 复制代码
// 从 1 开始递增
enum Status {
  Success = 1,  // 1
  Error,        // 2
  Loading,      // 3
  Pending       // 4
}

console.log(Status.Success); // 1
console.log(Status.Error);   // 2

也可以自定义所有元素的枚举值

TypeScript 复制代码
enum Priority {
  Low = 10,
  Medium = 20,
  High = 30,
  Urgent = 40
}

console.log(Priority.Medium); // 20
console.log(Priority.Urgent); // 40

可以通过下标访问,获取对应下标的key:

TypeScript 复制代码
enum Color {
  Red,
  Green,
  Blue
}

console.log(Color.Red);       // 0(正向映射)
console.log(Color[0]);        // "Red"(反向映射)
console.log(Color.Green);     // 1
console.log(Color[1]);        // "Green"

6.2 字符串枚举

枚举的value除了是数字,也可以是字符串

TypeScript 复制代码
enum Gender {
  Male = "MALE",
  Female = "FEMALE",
  Other = "OTHER"
}

// 使用
const userGender: Gender = Gender.Male;
console.log(userGender); // "MALE"

// 不支持反向映射
// console.log(Gender["MALE"]); // 错误:字符串枚举没有反向映射

6.3 异构枚举

枚举的value可以既有数字,又有字符串

TypeScript 复制代码
enum MixedEnum {
  No = 0,
  Yes = "YES"
}

console.log(MixedEnum.No);  // 0
console.log(MixedEnum.Yes); // "YES"

7.any 任意值 如果不希望对某些变量的类型进行静态类型检查,可以给变量定义为any类型。但与any类型进行计算的其他类型也会被覆盖为any,因此any可能会破坏其他类型。可以尽量少使用any。

8.void 空值 表示没有任何类型,void类型可以被赋值为undefined或者null

9.Null

10.undefined

11.never 表示永不存在的值的类型。用于不存在返回值的函数,或者中途会抛出错误的函数,或箭头函数。

never类型变量可以赋值给任何类型,但是任何其他类型都不能赋值给never。

never的例子:

TypeScript 复制代码
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
    throw new Error(message);
}

// 推断的返回值类型为never
function fail() {
    return error("Something failed");
}

// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
    while (true) {
    }
}

断言

有时,对于某个值,编码人员可能清除该值的详细信息,比如该对象上的某个方法等,但typescript会因为不知道其值,而在静态阶段对其进行报错。如果要消除这种报错,可以使用"断言",告知typescript该值一定符合静态审查。

1.<> 断言

用<>表示变量一定可以视作<>内的类型。

TypeScript 复制代码
let someValue: any = "this is a string";

let strLength: number = (<string>someValue).length;

2.as 断言

使用变量 as 类型,表示变量一定可以被视作某种类型。

TypeScript 复制代码
let someValue: any = "this is a string";

let strLength: number = (someValue as string).length;

一般情况下,<>断言和as断言都可以使用,但JSX只支持as断言。

类型别名type

通过type 类别别名 = 类型 的形式,可以给类型起别名,在实际使用时,使用别名表示变量的类型。

1.基础类型别名

TypeScript 复制代码
// 给 string 类型起别名
type UserName = string;
const name: UserName = "张三";

// 给 number 类型起别名
type Age = number;
const age: Age = 25;

2.联合类型别名

可以用 | 表示 类型可以是其中之一:

TypeScript 复制代码
// 定义可能是 string 或 number 的类型
type StringOrNumber = string | number;
let value: StringOrNumber;
value = "hello"; // 合法
value = 123; // 合法

3.交叉类型别名

可以用 & 表示,类型是两个别名的合并:

TypeScript 复制代码
// 合并两个类型的属性
type Person = { name: string };
type Employee = { id: number };
type EmployeePerson = Person & Employee;

const employee: EmployeePerson = {
  name: "李四",
  id: 1001
};

4.函数类型别名

类型别名也可以定义为函数的形式,规定函数的参数和返回值:

TypeScript 复制代码
// 定义函数类型
type AddFunction = (a: number, b: number) => number;

const add: AddFunction = (a, b) => a + b;
console.log(add(1, 2)); // 输出 3

interface 接口

interface(接口)的部分用法与type类似,但与type不同的是,interface用于定义对象的类型别名,同时,interface可以定义可选属性与只读属性,且interface定义的对象也可以被看做是类的一种规范,可以用来实现具体的类。

1.基本interface对象

TypeScript 复制代码
// 定义对象接口
interface Person {
  name: string;
  age: number;
}

const person: Person = {
  name: "赵六",
  age: 30
};

2.可选属性与只读属性

在interface中,可以使用readonly定义只读属性,使用description? 定义可选属性:

TypeScript 复制代码
interface Product {
  id: number;
  name: string;
  price: number;
  description?: string; // 可选属性
  readonly category: string; // 只读属性
}

const product: Product = {
  id: 101,
  name: "手机",
  price: 5999,
  category: "电子产品"
};

3.函数interface

interface定义函数别名:

TypeScript 复制代码
// 定义函数接口
interface GreetFunction {
  (name: string): string;
}

const greet: GreetFunction = (name) => `Hello, ${name}!`;
console.log(greet("孙七")); // 输出 "Hello, 孙七!"

4.类和interface

interface可以用来定义类的"契约或规范",类通过implements关键字来实现定义的接口,从而保证类符合接口定义的结构。

4.1 基本实现

TypeScript 复制代码
// 定义接口(契约)
interface Animal {
  name: string;
  eat(food: string): void;
  sleep(): void;
}

// 类实现接口
class Dog implements Animal {
  // 必须实现接口中的属性
  name: string;
  
  constructor(name: string) {
    this.name = name;
  }
  
  // 必须实现接口中的方法
  eat(food: string): void {
    console.log(`${this.name}正在吃${food}`);
  }
  
  sleep(): void {
    console.log(`${this.name}正在睡觉`);
  }
  
  // 类可以有接口中未定义的额外方法
  bark(): void {
    console.log(`${this.name}正在汪汪叫`);
  }
}

// 使用
const dog = new Dog("旺财");
dog.eat("骨头");    // 输出:旺财正在吃骨头
dog.sleep();        // 输出:旺财正在睡觉
dog.bark();         // 输出:旺财正在汪汪叫

4.2 类实现多个接口

通过implements 接口1,接口2,...... 的语法进行:

TypeScript 复制代码
interface Swimmer {
  swim(): void;
}

interface Runner {
  run(): void;
}

// 类同时实现两个接口
class Person implements Swimmer, Runner {
  swim(): void {
    console.log("正在游泳");
  }
  
  run(): void {
    console.log("正在跑步");
  }
}

const person = new Person();
person.swim();  // 输出:正在游泳
person.run();   // 输出:正在跑步

4.3 接口继承类

接口也可以继承自类,接口会继承类的所有成员,并可以添加新成员,实现该接口时,实现接口的类必须同时满足接口与接口继承自类的类要求:

TypeScript 复制代码
// 定义一个类
class Base {
  private id: number;
  protected name: string;
  public age: number;
  
  constructor(id: number, name: string, age: number) {
    this.id = id;
    this.name = name;
    this.age = age;
  }
}

// 接口继承类
interface Derived extends Base {
  // 接口可以添加新成员
  getInfo(): string;
}

// 实现接口的类必须同时满足Base类和Derived接口的要求
class DerivedClass extends Base implements Derived {
  constructor(id: number, name: string, age: number) {
    super(id, name, age);
  }
  
  getInfo(): string {
    // 可以访问继承的protected成员name和public成员age
    // 但无法访问private成员id
    return `姓名: ${this.name}, 年龄: ${this.age}`;
  }
}

const obj = new DerivedClass(1, "张三", 25);
console.log(obj.getInfo());  // 输出:姓名: 张三, 年龄: 25
相关推荐
海纳百川本尊760642 小时前
Flutter框架核心原理深度解析
前端
Shaneyxs2 小时前
从 0 到 1 实现CloudBase云开发 + 低代码全栈开发活动管理小程序(12)
前端
渔_2 小时前
uni-app 图片预览 + 长按保存,超实用!
前端
八哥程序员2 小时前
从DOM结构到布局流:display: content的深度解析与实战应用
前端·css
Shaneyxs2 小时前
从 0 到 1 实现CloudBase云开发 + 低代码全栈开发活动管理小程序(07)
前端
Shaneyxs2 小时前
从 0 到 1 实现CloudBase云开发 + 低代码全栈开发活动管理小程序(10)
前端
Shaneyxs2 小时前
从 0 到 1 实现CloudBase云开发 + 低代码全栈开发活动管理小程序(05)
前端
Shaneyxs2 小时前
从 0 到 1 实现CloudBase云开发 + 低代码全栈开发活动管理小程序(08)
前端