Day56:组件库封装-TypeScript入门

配置

安装tsc工具进行编译 npm i typescript -g

查看版本号:tsc -v

编译ts代码-需要使用tsc编译之后才能运行,TS为JS的衍生,浏览器不能直接识别TS语法:tsc xxx.ts

运行ts代码:node xxx.js 或者直接运行ts代码------ts-node xxx.ts

解除2584报错:

tsc --init

在生成的配置文件中的lib中,添加['DOM','ESNext']

一、基础类型

  1. srting
  2. number
  3. Boolean
  4. undefined
  5. null
  6. any:可以定义任何类型,但是相当于关闭了类型判断,所以不建议使用
typescript 复制代码
//类型注解
let str: string = '123'
let num: number = 123
let bol: boolean = false
let und: undefined = undefined
let nul: null = null
//尽量避免在ts中使用any 使用any就是关闭类型检查 
let a: any = true

二、类型推断与void类型

  1. 直接定义且赋值,ts会自动判断赋值的类型
  2. void类型,返回没有返回值的类型
  3. never类型,表示永远也无法达到的类型(比如报错
  4. unknown未知的类型,数据来源于外部(后端接口)
typescript 复制代码
//类型推断
let str1 = 'haha' //自动推断出来了str1是字符串类型
//void类型 返回没有返回值的类型
function fn(a: string): void {
    console.log(a)
}
//never类型 表示永远无法达到的类型
function err(): never {
    throw Error('wrong')
}
//unknown 未知的类型 数据来源于外部(后端接口)
let res: unknown
res = {}
export { }

三、对象,数组,函数

  1. Object/{}表示的是基类,object表示的是普通对象
  2. 定义数组时可以给数组指定类型arr:string arr:number
  3. 或者使用Array来指定数组的内容类型
  4. 数组也可以使用any类型来兼容数组中不同类型的数组元素(不推荐)
  5. 方法函数在写的时候需要给每一个传入参数和return结果规定类型
typescript 复制代码
let obj: object = { a: 1, b: 2 };
let arr: string[] = ["1", "2", "3"];
let arr1: number[] = [1, 2, 3];
let arr2: Array<boolean> = [false, true]
let arr3: any[] = [1, '2', true]
function fn(a: string, b: string): number {
    return Number(a) + Number(b)
}
fn('1', '2')
export { }

四、字面量

  1. 数字,字符串,布尔值类型
  2. 只能给字面量类型赋值字面量这个值,不能使用其他值
  3. 定义一个eat函数,他只能接收参数food,food值只能是rice noodle中的一个
  4. 联合类型function eat(food:'rice'|'noodle'),只要是其中一个即可
  5. 定义一个联合定义,可以使用type类型别名
typescript 复制代码
type x = string | number
function add(a:x,b:x):number {
  return Number(a) + Number(b)
}
add(2,'3')
  // 联合类型food 
  type f = 'rice'|'noodle'
// 方法eat
function eat(food:f) {
  console.log(food)
}
eat('rice') // 只能传入'rice'|'noodle'其中之一的值
  1. 类型别名常用来定义对象leixing
css 复制代码
type obj = {
  a:number;
  b:string
}  
let p:obj = {
  a:666,
  b:'777'
}
  1. 在ts中,如果需要换一种类型,都可以使用类型别名这种形式

五、枚举类型

很多时候,希望将一些字面量的联合类型列举起来,可以枚举的数据类型

  1. 定义一个eat方法,可以吃的东西------苹果,香蕉,桃子。枚举类型------联合列举字面量类型
ini 复制代码
enum Fruit = {
  APPLE = 'apple',
  BANANA = 'banana',
  PEACH = 'peach'
}
function eat(food:Fruit) {
  console.log(food)
}
eat(Fruit.APPLE)
  1. 枚举类型enum一般使用大写开头
  2. 枚举一般分为字符串枚举和数字枚举
  3. 枚举中有一个APPLE属性,它的值为'apple'
  4. 给eat传入的实参必须满足三中类型之一
  5. 代码语言中,经常会使用数字来表达状态。xhr.readyState监听接口是否正确返回数据(0=>4)
arduino 复制代码
enum State {
  // 不赋值的话,默认赋值从零开始依次递增
  BEGIN,
  READY,
  GET,
  HANDLE,
  RESPONSE
}
if(xhr.state = State.BEGIN) {
  '请求未发送'
}else if(xhr.state = State.READY) {
  '请求准备发送'
}...

六、接口

接口,接口描述对象或者函数

  1. 定义Animal,类型上有字符串name,数字age,联合类型 男|女 gender
  2. 接口有专用关键字interface
  3. 使用接口进行对对象类型的描述
css 复制代码
interface Animal {
  name:string;
  age:number;
  gender:'男'|'女'
}
let a1:Animal = {
  name:'peiqi',
  age:3,
  gender:'女'
}
a1.gender
  1. 定义对象类型时分隔符为分号
  2. 与类型别名的区别
    1. 类型别名有=赋值,接口没有
    2. 接口可以扩展,再interface一次Animal,再给它增加一组key,value,并不是覆盖原有类型,而是在原有类型基础上增加一个类型
css 复制代码
interface Animal {
  height:number
}  
  1. 由于接口的可扩展性,所以通常使用接口来描述对象
    1. 类型别名想要扩展需要使用交叉类型(和& 联合类型为或|)
    2. 定义两个类型别名,在第三个类型别名中交叉两个类型别名1&2,即可扩展,但很麻烦
  1. 接口可以继承
    1. 如果定义一个新的接口Dog,它可以继承自Animal,使用extends进行继承,dog就会拥有所有Animal的属性
typescript 复制代码
 interface Dog extends Animal {
  bark():void; /* 定义bark方法,没有返回值 */
} 
let a3:Dog = {
  name:'peiqi',
  age:3,
  gender:'女',
  height:100,
  bark() {
    console.log('wangwang')
  }
}
// 调用a3,a3.之后就会有a3的属性弹出
    1. 类型别名无法继承
  1. 实际应用中,对象是通过构造函数(类)来生成的,并不是直接通过字面量形式生成。类可以实现接口
    1. 类是如何实现接口的:使用implements进行类对于接口的实现
typescript 复制代码
class MyDog implements Dog {
  name: string
  age:number
  gender:'男'|'女'
  height:number
  constructor(
    _name:string;
    _age:number;
    _gender:'男'|'女',
    _height:number,
  ){
  this.name   = _name
  this.age    = _age
  this.gender = _gender
  this.height = _height
  }
  bark(): void{
    console.log(this.name)
  }
}
let a4:MyDog = new MyDog('xiaohei',4,'女',40)
a4.bark()
    1. 在类中定义------如果添加具体属性,需要先声明一下(ts中添加任何属性都必须声明。继承可以不用重新声明,但是class MyDog implements Dog这种必须要重新声明)
    2. 类中定义成员:普通属性应该定义在Constructor上,方法应该定义在原型身上
    3. 前面的age是定义的对象身上的属性,后面一个是传入的参数
    4. constructor后面进行的是传入的参数,是用来描述实参的形参
    5. this后面的表示要给成员添加什么样的属性。
    6. 方法是定义在原型上的,不用写this
    7. 前后定义的类型必须一致,否则无法这样赋值。
  1. 接口的索引访问:如果想要某一个索引不写值也可以运行,使用?,?表示这个索引可以有也可以没有
  2. Phone中有两个必须的索引,onSale是可选的索引,props是可以添加的自定义索引
typescript 复制代码
interface Phone {
  title:string;
  price:number;
  onSale?:boolean // ?表示这个索引可以有也可以没有
  [props: string] : any // 可以添加任意多的索引,索引类型可以自己定义
}
let p1:Phone = {
  title:'iphone15',
  price: 5999
}
let p2:Phone = {
  title:'iphone15',
  price: 5999,
  onSale: false
}
let p3:Phone = {
  title:'iphone15',
  price: 5999,
  weight: 400
}
  1. 索引访问类型:可以访问索引类型。
typescript 复制代码
// 11-索引访问类型
type s = Phone['price'] /* s为number */
// 12-访问Phone中的索引
type k = keyof Phone
let k1:k = 'onSale'
let k2:k = 'price'
// 13-接口描述函数
interface Fn {
  (a:number):number /* 参数为数字,返回值也是数字。接口描述函数用冒号链接 */
}
let fn:Fn = (a:number):number => {
  return a
}
fn(123)
  1. 收集到的phone这个接口上所有的索引值字面量组成的联合类型,只能访问Phone中的索引
  2. 接口描述函数:定义接口,实现接口,调用接口

七、元组

ts中元组可以理解为固定了长度和类型的数组(长度为3,类型分别为字符串,数字,布尔)

可变元组:如果只需要最后三个元素为[string, number, boolean]

typescript 复制代码
// 1
let turple:[string, number, boolean] = ['haah', 666, true]
// 2
let t2:[...any[], string, number, boolean] = [{}, 188, 'eee', 'haah', 666, true]

八、类型断言

类型注解,类型推断前面写了,类型断言:

typescript 复制代码
let b: number | string = '123'
let len:number = (b as string).length

b既可以是字符串类型也可以是数字类型,如果想访问b的length类型------如果b为number类型,则length不存在,只有b为string类型时,才可以访问b身上的length------当一个变量可能存在多个类型时,可以使用断言来缩小它的类型。将b断言为字符串类型,即可访问length

九、泛型

ref定义的变量上肯定有一个value属性,value应该是什么类型呢?需要一个什么都可以的类型,但绝对不能是any

csharp 复制代码
interface Ref<T> {
  value: T // 定义Ref接口和定义了任意一个类型T,其实写什么都行
} 
let r1:Ref<string> = {
  value:'haha'
}
let r2:Ref<number> = {
  value:321
}
// fn传入的参数和返回的参数是一个类型
function fn<K>(a:K):K {
  return a
}
fn('haha') 
fn(123)

定义Ref接口和定义了任意一个类型T,其实写什么都行。这样定义的类型可以传入任意类型

在使用接口的时候,需要定义需要传入的类型,将泛型具体化。相当于泛型是一个形式参数,泛型是用来传递类型的。在具体使用的时候需要传入实际参数(具体的类型)

如果在定义方法的时候定义它需要传入和返回同一种类型的参数,则在实际使用的时候传入什么样的参数,则传入和返回的都是这个参数的类型

练习

实现一个类ArrayList,这个类具有数组的添加元素(add)和访问数组(get)的功能。利用泛型来实现这样一个类

typescript 复制代码
class ArrayList<T> {
  arr:T[] // 定义一个泛型空数组
  index: number = 0 // 表示数组元素的个数,不表示索引
  constructor(){
    this.arr = [] // 开始时置空数组
  }
  // 添加元素
  add(element:T){
    this.arr[this.index++] = element // 先执行再index递增,添加了元素就增加长度
  }
  // 访问元素
  get(index:number){
    return this.arr[index] ? this.arr[index] : undefined
  }
}
let arr1 = new ArrayList<number>()
arr1.add(1)
console.log(arr1.arr) // [1]
arr1.add(2)
console.log(arr1.arr) // [1,2]
console.log(arr1.arr[1]) // 2
console.log(arr1.arr[2]) // undefined

泛型和泛型约束

写一个方法,可以访问对象身上的属性

scala 复制代码
function getProperty<T extends object,K extends keyof T>(obj:T,key:K){
  return obj[key]
}
getProperty({a:1,b:2},'a') // key只能是a或者b,

obj表示整个对象,obj的T extends object约束T为普通对象类型。key的K约束为K extends keyof T,在给obj给了内容后,key只能是obj的key

相关推荐
崔庆才丨静觅8 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60618 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了9 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅9 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅9 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅9 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment9 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅10 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊10 小时前
jwt介绍
前端
爱敲代码的小鱼10 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax