一.TypeScript是什么
- TypeScript是由微软开发,是Javascript的超集,它支持ES6语法,支持面向对象编程的概念,如:静态类型检查,类,接口,继承,泛型等。
- TypeScript是一种静态类型检查的语言,提供了类型注解,在代码编译阶段就可以检查出数据类型的错误。
- 浏览器不能直接运行 TypeScript 代码, TypeScript 在编译阶段需要编译器编译成纯JavaScript来运行,再交由浏览器解析器执行。
二.TypeScript的特性
- 类型声明 :指在变量、函数、对象等后面显式指定数据类型。
- 类型推断:ts 中没有声明变量类型时会自动推断变量的类型
- 接口(Interface):ts 中用接口来定义对象的结构和规范。
- 枚举(Enum):用于取值被限定在一定范围内的场景,可以定义一组命名常量
- 类型别名(Type):type可以给类型起一个别名。
- 泛型编程:写代码时使用⼀些以后才指定的类型,用于编写可复用组件或函数
- 联合类型:表示变量可以是 多种类型之一。
- 元组(Tuple):元组合并了不同类型的对象,相当于一个可以装不同类型数据的数组
2.1 类型声明
TypeScript 使用 : 来对变量或函数形参进行类型声明,显式指定数据类型。
基本语法:
let 变量名: 类型 = 值
举例:
let name: string = "Tom" //变量name只能存储字符串
let age: number = 20 //变量age只能存储数值
let isLogin: boolean = true //变量isLogin只能存储布尔值
//函数参数x必须是数字,参数y也必须是数字,函数返回值也必须是数字
function demo(x:number,y:number):number{
return x + y
}
demo(1,2)
常见基本类型:
| 类型 | 含义 |
|---|---|
| string | 字符串 |
| number | 数字 |
| boolean | 布尔 |
| null | 空 |
| undefined | 未定义 |
| any | 任意类型 |
| unknown | 安全的任意类型 |
| void | 无返回值 |
| never | 永远不会返回 |
2.2 类型推断
TypeScript 会根据我们的代码,自动进行类型推断。比如:
let age = 18
let arr = [1, 2, 3]
TypeScript 会自动推断为:
age: number
arr:number[]
但如果写成:let data;这种会被推断为any,会失去类型检查
2.3 类型别名(Type)
type 可以为任意类型起一个别名,更方便地进行类型复用和扩展。
基本用法:
类型别名使用 type 关键字定义。 type 后跟类型名称。
请注意:type是用 = 连接变量和类型,这一点与接口有所不同。接口不用 = 连接。
//基本类型别名
type num = number;
let price: num
price = 10
//对象类型别名
type User = {
id: number
name: string
age: number
}
const user: User = {
id: 1,
name: "Tom",
age: 20
}
type可以定义更多的类型,这是type最大的优势
2.3.1 联合类型(T | U)
联合类型是⼀种高级类型,它表示一个值 可以是几种不同类型之一。
type ID = string | number
type Gender = '男' | '女'
let id: ID
id = 100
id = "A001"
function logGender(str:Gender){
console.log(str)
}
logGender('男')
2.3.2 交叉类型(对象合并 T & U)
交叉类型 允许将多个类型合并为一个类型。合并后的类型将拥有所有被合并类型的成员。
交叉类型通常用于对象类型。
//⾯积
type Area = {
height: number; //⾼
width: number; //宽
};
//地址
type Address = {
num: number; //楼号
cell: number; //单元号
room: string; //房间号
};
// 定义类型House,且House是Area和Address组成的交叉类型
type House = Area & Address;
const house: House = {
height: 180,
width: 75,
num: 6,
cell: 3,
room: '702'
}
2.3.3 基本类型别名
type Name = string
type Age = number
2.4接口(Interface)
interface 用于描述对象的结构,通常用于定义 对象类型规范。
其主要作用是为:类、对象、函数等规定一种契约,这样可以确保代码的⼀致性和类型安全,但要注意 interface 只能定义格式,不能包含任何实现!
在 TypeScript 中,用 implements 实现接口,用expends继承接口。
1. implements 用于 类实现接口。
意思是:这个类必须按照接口规定 实现对应的属性和方法。一个类可以实现多个接口。
1.expends的作用是 继承已有类型的属性和方法。
它既可以用于:
- 接口继承接口
- 类继承类
2.4.1定义类结构
// PersonInterface接⼝,⽤与限制Person类的格式
interface PersonInterface {
name: string
age: number
speak(n: number): void
}
// 定义⼀个类 Person,实现PersonInterface 接⼝
class Person implements PersonInterface {
constructor(
public name: string,
public age: number
) { }
// 实现接⼝中的speak ⽅法
speak(n: number): void {
for (let i = 0; i < n; i++) {
//打印出包含名字和年龄的问候语句
console.log(`你好,我叫${this.name},我的年龄是${this.age}`);
}
}
}
// 创建⼀个 Person 类的实例p1,传⼊名字'tom'和年龄18
const p1 = new Person('tom', 18);
p1.speak(3)
2.4.2 定义对象结构
interface UserInterface {
name: string
readonly gender: string // 只读属性
age?: number // 可选属性
run: (n: number) => void
}
const user: UserInterface = {
name: "张三",
gender: '男',
age: 18,
run(n) {
console.log(`奔跑了${n}⽶`)
}
}
2.4.3 定义函数结构
interface CountInterface {
(a: number, b: number): number;
}
const count: CountInterface = (x, y) => {
return x + y
}
2.4.5 接口之间的继承
一个 interface 继承另一个 interface,从而实现代码的复用。
interface PersonInterface {
name: string // 姓名
age: number // 年龄
}
interface StudentInterface extends PersonInterface {
grade: string // 年级
}
const stu: StudentInterface = {
name: "张三",
age: 25,
grade:'高三'
}
2.4.6 接口自动合并(可重复定义)
// PersonInterface接⼝
interface PersonInterface {
// 属性声明
name: string
age: number
}
// 给PersonInterface接⼝添加新属性
interface PersonInterface {
// ⽅法声明
speak(): void
}
// Person类实现PersonInterface
class Person implements PersonInterface {
name: string
age: number
// 构造器
constructor(name: string, age: number) {
this.name = name
this.age = age
}
// ⽅法
speak() {
console.log('你好!我是⽼师:', this.name)
}
}
总结:何时使用接口?
- 定义对象的格式: 描述数据模型、API 响应格式、配置对象........等等
- 类的契约:规定⼀个类需要实现哪些属性和方法。
- 扩展已有接口:一般用于扩展第三方库的类型。
总结:interface 和type的区别?
相同点: interface 和 type 都可以用于定义对象结构,在定义对象结构时两者可以互换。
不同点:
- interface :更专注于定义对象和类的结构,⽀持继承、合并。
- type :可以定义类型别名、联合类型、交叉类型,但不支持继承和自动合并。
2.5 枚举(Enum)
枚举(enum)用于 定义一组命名常量。
2.5.1 数字枚举
数字枚举是默认的枚举类型,成员的值是数字。
其成员的值从0自动递增,且数字枚举还具备反向映射的特点,可以通过值来获取对应的枚举成员名称 。
//定义⼀个描述【上下左右】⽅向的枚举Direction
enum Direction {
Up,
Down,
Left,
Right
}
console.log(Direction) //打印Direction会看到如下内容
/*
{
0:'Up',
1:'Down',
2:'Left',
3:'Right',
Up:0, //反向映射
Down:1,
Left:2,
Right:3
} */
// 反向映射
console.log(Direction.Up) //0
console.log(Direction[0]) //“Up”
// 此⾏代码报错,枚举中的属性是只读的
Direction.Up = 'shang'
也可以指定枚举成员的初始值,其后的成员值会自动递增。
enum Direction {
Up = 6,
Down,
Left,
Right
}
console.log(Direction.Up); // 6
console.log(Direction.Down); // 7
2.5.2 字符串枚举
字符串枚举的成员值是 字符串。
enum Direction {
Up = "up",
Down = "down",
Left = "left",
Right = "right"
}
let dir: Direction = Direction.Up
console.log(dir) // "up"
特点:
- 每个成员必须 手动赋值
- 没有反向映射
- 可读性更好
2.5.3 常量枚举
常量枚举用于提高性能。
官方描述:常量枚举是⼀种特殊枚举类型,它使用内联,避免生成⼀些额外的代码。
何为编译时内联?
所谓“ 内联” ,就是 TypeScript 在编译时,会将枚举成员引用替换为它们的实际值, 而不是生成额外的枚举对象。这可以减少生成的 JavaScript 代码量,并提高运行时性能。
const enum Direction {
Up,
Down,
Left,
Right
}
let dir = Direction.Up // 0
编译后的 JavaScript:
var dir = 0;
可以看到:
- 枚举对象不会生成
- 直接替换为常量值
2.6 泛型
泛型允许我们在定义函数、类或接口时不指定具体类型,使用类型参数来表示未指定的类型,这些参数在具体使用时,才被指定具体的类型。
泛型能让同一段代码适用于多种类型,同时仍然保持类型的安全性。
举例:如下代码中<T>就是泛型,设置泛型后即可在函数中使用T来表示该类型:
//这里的T就是泛型类型变量
function identity<T>(value: T): T {
return value
}
//调用
identity<string>("hello")
identity<number>(100)
//类型自动保持一致
let result = identity("hello")
2.6.1 泛型函数
泛型最常见的场景是 函数。
2.6.2 泛型接口
接口也可以使用泛型。
interface ApiResponse<T> {
code: number
data: T
message: string
}
interface User {
id: number
name: string
}
const res: ApiResponse<User> = {
code: 200,
data: {
id: 1,
name: "Tom"
},
message: "success"
}
好处:
- API 返回结构统一
- data 可以是任意类型
2.6.3 泛型类
类也可以使用泛型。
class Person<T> {
constructor(
public name: string,
public age: number,
public extraInfo: T
) {}
speak() {
console.log(`我叫${this.name}今年${this.age}岁了`)
console.log(this.extraInfo)
}
}
const p1 = new Person<number>("tom", 30, 250)
type JobInfo = {
title: string;
company: string;
}
const p2 = new Person<JobInfo>("tom", 30, { title: '研发总监', company: 'xxx公司' })
2.6.4 多个泛型参数
泛型可以有多个参数
2.6.5 泛型约束(extends)
有时候我们希望 泛型必须满足某种条件。
可以使用 extends.
2.7 元组(Tuple)
元组 (Tuple) 是⼀种特殊的数组类型,可以存储固定数量的元素,并且每个元素的类型是已知的且可以不同。元组用于精确描述⼀组值的类型, ? 表示可选元素
//第⼀个元素必须是string类型,第⼆个元素必须是number类型。
let arr1: [string,number]
//第⼀个元素必须是number类型,第⼆个元素是可选的,如果存在,必须是boolean类型。
let arr2: [number,boolean?]
//第⼀个元素必须是number类型,后⾯的元素可以是任意数量的string 类型
let arr3: [number,...string[]]
//可以赋值
arr1 = ['hello',123]
arr2 = [100,false]
arr2 = [200]
arr3 = [100,'hello','world']
arr3 = [100]
// 不可以赋值,arr1声明时是两个元素,赋值的是三个
arr1 = ['hello',123,false]
最后
如果这篇文章对你有帮助的话,就点个赞吧!