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
相关推荐
灵感__idea13 小时前
Hello 算法:贪心的世界
前端·javascript·算法
GreenTea14 小时前
一文搞懂Harness Engineering与Meta-Harness
前端·人工智能·后端
killerbasd16 小时前
牧苏苏传 我不装了 4/7
前端·javascript·vue.js
吴声子夜歌16 小时前
ES6——二进制数组详解
前端·ecmascript·es6
码事漫谈17 小时前
手把手带你部署本地模型,让你Token自由(小白专属)
前端·后端
ZC跨境爬虫17 小时前
【爬虫实战对比】Requests vs Scrapy 笔趣阁小说爬虫,从单线程到高效并发的全方位升级
前端·爬虫·scrapy·html
爱上好庆祝17 小时前
svg图片
前端·css·学习·html·css3
橘子编程17 小时前
JavaScript与TypeScript终极指南
javascript·ubuntu·typescript
王夏奇17 小时前
python中的__all__ 具体用法
java·前端·python
叫我一声阿雷吧17 小时前
JS 入门通关手册(45):浏览器渲染原理与重绘重排(性能优化核心,面试必考
javascript·前端面试·前端性能优化·浏览器渲染·浏览器渲染原理,重排重绘·reflow·repaint