TypeScript 的核心知识点合集

1, 了解TypeScript

TS是带类型语法的JS : TypeScript 是一种带有 类型语法 的 JavaScript 语言,在任何使用 JavaScript 的开发场景中都可以使用。

JavaScript 代码 没有明确的类型  let age = 18

TypeScript 代码 有明确的类型,可以指定age是number类型(数值类型)  let age: number = 18

注意:TS 需要编译才能在浏览器运行。 

2,TS 优势:

  • JS 是动态类型的编程语言,动态类型最大的特点就是它只能在 代码执行 期间做类型的相关检查,所以往往你发现问题的时候,已经晚了。
  • TS 是静态类型的编程语言,代码会先进行编译然后去执行,在 代码编译 期间做类型的相关检查,如果有问题编译是不通过的,也就暴露出了问题。
  • 配合 VSCode 等开发工具,TS 可以提前到在 编写代码 的时候就能发现问题,更准确更快的处理错误。

 TS优势总结

  • 更早发现错误,提高开发效率
  • 随时随地提示,增强开发体验
  • 强大类型系统,代码可维护性更好,重构代码更容易
  • 类型推断机制,减少不必要类型注解,让编码更简单
  • 最后:Vue3源码TS重写,React和TS完美配合,Angular默认支持TS,大中型前端项目首选。

3,如何使用 TypeScript 编译ts代码

全局安装:
# npm 安装
npm i -g typescript
# yarn 安装
yarn global add typescript
# 部分mac电脑安装需要sudo权限
# sudo npm i -g typescript
# sudo yarn global add typescript



查看版本:
tsc -v

编译ts流程:新建hello.ts文件  ====> 在当前根目录打开命令窗口,执行tsc hello.ts 命令,同级目录生成 hello.js 文件===>验证一下

  • 在开发中:一般使用 webpack vite 等工具自动构建编译。

创建 vue-ts 项目 

任选一种方式:
# npm 6.x
npm create vite@latest my-vue-ts-app --template vue-ts

# npm 7+, extra double-dash is needed:
npm create vite@latest my-vue-ts-app -- --template vue-ts

# yarn
yarn create vite my-vue-ts-app --template vue-ts

# pnpm
pnpm create vite my-vue-ts-app --template vue-ts

4,TypeScript 核心

     首先了解一下js的数据类型有哪些:js的数据类型一共有8种,

        简单数据类型:number, string ,boolean, null,undefined,Symbol,BigInt

        复杂数据类型:Object【Object是个大类,function函数、array数组、date日期...等都归属于Object】

   一 类型注解  

  • 变量后面约定类型的语法,就是类型注解

约定了什么类型,就只能给该变量赋值什么类型的值,否则报错。

// 约定变量 age 的类型为 number 类型

let age: number = 18;                    

age = 19;

二 数组类型

// 数组类型

let arr: Array<number> = [1, 2, 3, 4, 5]

let arr1: number[] = [1, 2, 3, 4, 5]

let arr2: string[] = ['1', '2', '3']

三  联合类型:

  • 类型与类型之间使用 | 连接,代表类型可以是它们当中的其中一种,这种类型叫:联合类型

第一种:

let count: number | string = 2           // count的值只能是number类型或者string类型

第二种:

let obj: { id: number, name: string } = { id: 1, name: 'jack' }

let obj2: { id: number, name: string } | number | number[ ] = { id: 1, name: 'jack' }  

  obj2 的值类型可以是这几种:{ id: number, name: string } |  number  |  number[ ]

第三种:

let arr3: ( number |  string |  number[ ] )[ ] = [1, 2, 3, '4', [1, ‘2’] ]

第四种:

let list: {

  id: number;

  name: string;

  hobby: string[];

  family: {

    mather: string;

  };

} = {

  id: 1,

  name: 'jack',

  hobby: ['游泳', '唱歌'],

  family: {

    mather: '母亲'

  }

}

四 函数类型

  • 给函数指定类型,其实是给 参数 和 返回值 指定类型。
  • 两种写法:
    • 在函数基础上 分别指定 参数和返回值类型
    • 使用类型别名 同时指定 参数和返回值类型

// 普通函数类型  定义函数的参数类型是number,返回值类型是string

function add(a: number, b: number): string {

  return '12'

}

add(1, 2)

// 箭头函数  定义函数的参数 返回值类型都是number

const add1 = (a: number, b: number): number => {

  return 12

}

add1(1, 2)

// 使用函数类型别名 同时指定 参数和返回值类型:

type F = (a: number, b: number) => string

const add2: F = (a, b) => {

  return '12'

}

add2(1, 2)

const add2: (a: number, b: number) => number= (a, b) => {

    return a

  }

add2(1, 2)

五 类型别名:

  • 当同一类型(复杂)被多次使用时,可以通过类型别名,简化 该类型的使用

// 对象类型别名

type N =number

type S=string

type T = {

  id: N;

  name: S;

  hobby: S[ ];

  family: {

    mather: S;

  } 

  say: () => string

  fn(): void

}

let list: T = {

  id: 1,

  name: 'jack',

  hobby: ['游泳', '唱歌'],

  family: {

    mather: '母亲'

  },

   say: () => {

    return '123'

  },

   fn() {

    return 456

  }

}

// 函数类型别名:

type F = (a: number, b: number) => string

const add3: F = (a, b) => {

  return '12'

}

add2(1, 2)

六 void 类型

对于返回值不确定的可以使用void   void跟undefined是两种类型   类型是undefined 值只有undefined

例如: 后台返回的数据 不确定类型的情况下 可以用void  函数的返回值不确定类型的情况下也可以用void

type F1 = (a: number, b: number) => undefined

const add4: F1 = (a, b) => {

  return undefined

}

add4(1, 2)

七 字面量类型

// 字面量类型

// let num:123=123  字母量类型

// num=456  会报错

const num2: 456 = 456

let num3: number = 789

num3 = 666

八 可选参数

  • 如果函数的参数,可以传也可以不传,这种情况就可以使用 可选参数 语法,参数后加 ? 即可

//  第一种

type F2 = (a?: number, b?: number) => undefined

const add5: F2 = (a, b) => {

  return undefined

}

add5()  //可以不传参  在上面的a后面加?

// 函数的可选参数有两种情况:箭头函数跟普通函数  ?写的位置不一样 如下:

type list1 = {

  id: number

  name: string

  hobby: string[]

  family: {

    mather: string

  },

  say?: () => string

  fn?(): void

}

let list4: list1 = {

  id: 1,

  name: 'jack',

  hobby: ['游泳', '唱歌'],

  family: {

    mather: '母亲'

  },

  // say: () => {

  //   return '123'

  // },

  // fn() {

  //   return 456

  // }

}

九 接口 interface

  • interface 后面是接口名称,和类型别名的意思一样。简单来说,接口后面是接类型。

//接口 interface 没有等号 专门定义对象数据类型

interface Iperson {

  id: number

  name: string

}

const obj1: Iperson = {

  id: 1,

  name: 'jack'

}

// type 类型别名 有等号 可以定义所有数据类型

   type Toby={

    id:number

    name:string

  }

  const obj1:Toby={

   id:1,

   name:'jack'

 }

 十 interface 继承

        使用 extends 实现接口继承,达到类型复用

// 接口 interface  继承 extends  不用extends 就重复定义会合并

interface Iperson {

  id: number

  name: string

}

interface Iperson2 extends Iperson {  //Iperson2 继承 Iperson 的类型

  age: number

  hobby: string[]

}

const obj1: Iperson2 = {

  id: 1,

  name: 'jack',

  age: 18,

  hobby: ['rap']

}

 十一  type 交叉类型

// 类型别名 type & 继承  type不可以重复定义

type Tperson = {

  id: number

  name: string

}

type Tperson2 = Tperson & {

  age: number

  hobby: ['rap']

}

const obj3: Tperson2 = {

  id: 1,

  name: 'jack',

  age: 18,

  hobby: ['rap']

}

interface 和 type 的相同点和区别 小结:

  • 它们都可以定义对象类型
  • 它们都可以复用,interface 使用 extends , type 使用 &
  • type 不能重复定义,interface 可以重复会合并

 十二 类型推断 as

// 类型断言:as

// 但是我们明确知道获取的是一个 A 元素,可以通过 类型断言 给它指定一个更具体的类型。标签的类型

const aLink = document.getElementById('link') as HTMLAnchorElement  //获取的元素是一个a标签

const img = document.getElementById('img') as HTMLImageElement

type T2 = {

  id: number

  name: string

  arr: number[]

}

let obj7 = {} as T2  //类型断言

obj7.arr = [1, 2]   //obj7. 后面会有提示  只能拿到以下3个

obj7.id = 3

obj7.name = 'jack'

// 类型推断: typeof 后面接值 ====> 返回的是 类型

const obj4 = {

  id: 1,

  name: 'jack'

}

type Tperson4 = typeof obj4  // 进行类型推断

let obj5 = {} as Tperson4  // 结合as类型断言

obj5.id = 2

obj.name = 'rose'

 十三 any 类型

  • 显式any情况:当变量的类型指定为 any 的时候,不会有任何错误,也不会有代码提示,TS会忽略类型检查
  • any 的使用越多,程序可能出现的漏洞越多,因此不推荐使用 any 类型,尽量避免使用。

 十四 类型推断  typeof   keyof

  • 在 TS 中存在类型推断机制,在没有指定类型的情况下,TS 也会给变量提供类型。
  • typeof  后面接的是值  返回的是值的类型
  • keyof  后面接的是类型  返回的也是类型  或者说 返回的是类型中的键组合的字面量联合类型

// 类型推断: typeof 后面接值 ====> 返回的是 类型

const obj4 = {

  id: 1,

  name: 'jack'

}

type Tperson4 = typeof obj4  // 进行类型推断

let obj5 = {} as Tperson4  // 结合as类型断言

obj5.id = 2

obj.name = 'rose'

// keyof 后面接的是类型 返回的也是类型

const res = {

  info: 'admin',

  introduce: '数据',

  mobile: 13020203030

}

type Tt = typeof res

type key = keyof Tt  // 返回的是 "info" | "introduce" | "mobile"  返回的是类型中的键 组成的字面量联合类型

 十五 泛型  

  • 在TypeScript中,泛型是一种创建可复用代码组件的工具。这种组件不只能被一种类型使用,而是能被多种类型复用。类似于参数的作用,泛型是一种用以增强类型(types)、接口(interfaces)、函数类型等能力的非常可靠的手段。

 泛型别名 

// 泛型别名

type user = {

  id: number

  age: number

}

type Goods = {

  hobby: string[]

  gender: string

}

type Data<T> = {

  id: number

  get: string

  res: T

}

type userInfo = Data<user>

/* 返回的结果如下

  {

    id:number

    get:string

    res: {

    id: number

    age: number

  }

}

*/

type userInfo1 = Data<Goods>

/* 返回的结果如下

  {

    id:number

    get:string

    res: {

    hobby: string[]

    gender: string

  }

}

*/

type Data1<T, S> = {

  id: number

  get: string

  res: T

  code: S

}

type userInfo3 = Data1<Goods, user>

 泛型接口

// 泛型接口 没有等号=

interface Iperson1<T, S = string> {

  id: number

  code: number

  messgae: S

  data: T

}

type Iperson3 = Iperson1<number>

// 验证类型Iperson3

const obj6: Iperson3 = {

  id: 1,

  code: 2,

  messgae: '456',

  data: 789,

}

 泛型函数

// 泛型函数

// 函数名称后加上 <Q> , Q是类型参数,是个类型变量

// 当你调用函数的时候,传入具体的类型,Q 或捕获到这个类型,函数任何位置均可使用。

type Q = number

function fn1<Q>(a: Q): Q {

  return a

}

// add1<Q>('123')  //会提示不能赋值string

fn1('123')  //会自动进行类型推断

// 泛型函数继承

type F3 = string

function fn2<Q extends F3>(a: Q): Q {

  return a

}

fn2('1')

// 泛型函数  继承 类型推断

const c1 = { id: 1 }

function fn3<Q extends typeof c1>(a: Q): Q {

  return a

}

fn3({ id: 2 })

// 泛型函数  继承 keyof

type c2 = { id: 1 }  //keyof c2 返回c2类型的键   、Q extends keyof c2 Q继承c2返回的类型中的键 也就是字面量id

function fn4<Q extends keyof c2>(a: Q): Q {

  return a

}

fn4('id')  //参数 只能输入'id'

枚举 

// 枚举  enum  

// 可以设定初始值

enum Day {

  sunday,

  monday,

  tuesday,

  wednesday,

  thursday,

  friday,

  saturday

}

function fn5(Day: Day) {

  return Day

}

fn5(Day.sunday)

 TypeScript 应用

前提:script 加上 lang="ts" 才能写ts代码

<script setup lang="ts"></script>

 defineProps的TS写法  

  1. defineProps 的基本使用:

 父传:

<script setup lang='ts'>

     // 父传

     import son from './components/son.vue'

     const sum = 100

</script>

<template>

  <div>

    <div>我是父组件</div>

    <hr />

    <son :money="sum" :car="'宝马x5'" num="你好"></son>

</div>

</template>

<style lang='less'  scoped></style>

 

 子收:

 

<script setup lang='ts'>

//1 v3的写法

// defineProps({

//   money: Number,

//   car: {

//   type:String

// },

//   num: String

// })

//2 ts写法 没有默认值的写法: 泛型的写法

// defineProps<{

//   money: number

//   num: string

//   car?: string   //可选参数

// }>()

// 3 ts写法 有默认值的写法:withDefaults(defineProps<>(),{默认值})  

// 父组件没传car的情况下就显示默认值 ,父组件传值了显示传的值

// withDefaults(defineProps<{

//   money: number

//   num: string

//   car?: string   //可选参数

// }>(), {

//   car: '凯迪拉克'

// })

//  4 有默认值的简易写法  父组件没传car的情况下就显示默认值 car = '凯迪拉克'

let { money, num, car = '凯迪拉克' } = defineProps<{

  money: number

  num: string

  car?: string

}>()

</script>

<template>

  <div>

    ===vue3

    ===={{ money }}==={{ num }}==={{ car }}

    <div>我是子组件son</div>

  </div>

</template>

<style lang='less'  scoped>

</style>

 defineEmits的TS写法  

  1. defineEmits 的基本用法:

vue3写法:

const emit = defineEmits(['事件名'])

    2.defineEmits 通过泛型参数来定义,可以实现更细粒度的校验:

 ts写法:

ts 泛型  const emits = defineEmits<>()

const emits = defineEmits<{

  (e: 'handel', s: string): void

  (e: 'handel2', s: number): void

}>()

 子传: 

子传

<script setup lang='ts'>

// 第一种子传父 vue3

// const emits = defineEmits(['handel'])

// const btn = () => {

//   emits('handel', '我是子组件son传的值')

// }

// 第二种子传父  ts泛型  const emits = defineEmits<>()

const emits = defineEmits<{

  (e: 'handel', s: string): void

  (e: 'handel2', s: number): void

}>()

const btn = () => {

  // 子向父传值

  emits('handel', '我是子组件son传的第一个值')

}

const btn2 = () => {

  // 子向父传值

  emits('handel2', 123456)

}

</script>

<template>

  <div>

    <div>我是children子组件</div>

    <button @click="btn">子传父</button>

    <button @click="btn2">子传父2</button>

  </div>

</template>

<style lang='less'  scoped>

</style>

父收 

<script setup lang='ts'>

// 父收

        import children from './components/children.vue'

// 第一种方法

// const msg = () => {

//           console.log('handel')

// }

// 第二种方法:

import { ref } from 'vue'

const msg = ref('')

const msg2 = ref(1)


 

</script>

<template>

  <div>

    御剑乘风来,除魔天地间!===vue3

    <div>我是父组件</div>

    <hr />

    <!-- <children @handel="msg"></children>  第一种方法-->

    <!-- 子向父传值 第二种方法-->

    ===={{ msg }}

    ===={{ msg2 }}

    <children @handel="msg = $event" @handel2="msg2 = 123456"></children>

  </div>

</template>

<style lang='less'  scoped>

</style>

 

ref的TS写法  +  ref获取dom元素

ref() 会隐式的依据数据推导类型

  1. 如果是简单类型,推荐使用类型推导:
  2. 如果是复杂类型,推荐指定泛型:复杂数据一般是后台返回数据,默认值是空,无法进行类型推导。

<script setup lang='ts'>

        import { ref } from "vue";

        type T = {

          id: number

          name: string

        }

        let list = ref<T[ ]>([ ])  //<T[ ]> 表示一个list这个数组里面的每一个数据都是T这样的对象类型{id:123,name:"jack"}

        list.value.push({ id: 123, name: 'rose' })  //

</script>

<template>

          <div>

            ===vue3

          </div>

</template>

<style lang='less'  scoped>

</style>

 reactive的TS写法

reactive() 也会隐式的依据数据推导类型

  1. 默认值属性是固定的,推荐使用类型推导:
  2. 根据默认值推导不出我们需要的类型,推荐使用接口或者类型别名给变量指定类型:

推荐使用ref( ) 

computed和TS

  1. computed() 会从其计算函数的返回值上推导出类型:
  2. 可以通过泛型参数显式指定类型:

<script setup lang='ts'>

import { ref, computed } from "vue";

type T = {

  id: number

  name: string

}

let list = ref<T[]>([])  //<T[]> 表示一个list这个数组里面的每一个数据都是T这样的对象类型{id:123,name:"jack"}

list.value.push({ id: 123, name: 'rose' })  //

// const newList = computed(() => {  //vue3写法

//   return list.value

// })

const newList = computed<T[]>(() => {  //泛型写法  T[]返回值的类型

  return list.value

})

let num = ref(100)

const newNum = computed<string>(() => {

  return (num.value * 10).toFixed(2)  //保留2位小数

})

</script>

<template>

  <div>

    御剑乘风来,除魔天地间!===vue3

    ===={{ newList }}==={{ newNum }}

  </div>

</template>

<style lang='less'  scoped>

</style>

事件处理与TS 

<script setup lang='ts'>

import { ref, onMounted } from "vue"

// 事件对象 ===ts

const handelChange = (e: Event) => {

  // 类型断言

  let val = (e.target as HTMLInputElement).value

  console.log(val, 99);

}

// ref获取dom元素

const dom = ref<HTMLInputElement | null>(null)

onMounted(() => {

  // console.log(dom.value?.value,77);

  // if(dom.value){

  //   console.log(dom.value.value,88);

  // }

  // ts非空断言

  console.log(dom.value!.value, 88);

})

</script>

<template>

  <div>

    御剑乘风来,除魔天地间!===vue3

    <input ref="dom" type="text" @change="handelChange" value="默认值" />

  </div>

</template>

<style lang='less'  scoped>

</style>

 TypeScript类型声明文件

项目中安装的第三方库里面都是打包后的JS代码,但是我们使用的时候却有对应的TS类型提示,这是为什么呢?

  • 在第三方库中的JS代码都有对应的 TS类型声明文件

什么是类型什么文件?

  • 通俗地来讲,在 TypeScript 中以 .d.ts 为后缀的文件,我们称之为 TypeScript 类型声明文件。它的主要作用是描述 JavaScript 模块内所有导出成员的类型信息。

TS 中有两种文件类型:.ts 文件 .d.ts 文件作用是啥?

  • .ts 文件:
    1. 既包含类型信息又可执行代码
    2. 可以被编译为 .js 文件,然后,执行代码
    3. 用途:编写程序代码的地方
  • .d.ts 文件:
    1. 只包含类型信息的类型声明文件
    2. 不会生成 .js 文件,仅用于提供类型信息,在.d.ts文件中不允许出现可执行的代码,只用于提供类型
    3. 用途:为 JS 提供类型信息

小结:

  • .ts 是 implementation 代码实现文件
  • .d.ts 是 declaration 类型声明文件
  • 如果要为 JS 库或者模块提供类型,就需要类型声明文件

第三方库类型声明文件

        给第三方库添加对应的类型声明文件

首先,常用的第三方库都有相应的类型声明文件,只是使用的方式不同而已。

情况1:库本身自带类型声明文件

  • 比如:axios,安装后可查看 node_modules/axios 可发现对应的类型声明文件。
  • 导入 axios 后就会加载对应的类型文件,提供该库的类型声明。

情况2:由 DefinitelyTyped 提供

  • 比如:jquery,安装后导入,提示:需要安装 @types/jquery 类型声明包
  •  (pnpm i  @types/jquery)
  • DefinitelyTyped 是一个 github 仓库,用来提供高质量 TypeScript 类型声明
  • 当安装 @types/* 类型声明包后,TS 也会自动加载该类声明包,以提供该库的类型声明

自定义类型声明文件  共享类型

        使用类型声明文件提供需要共享的TS类型

  • 如果多个 .ts 文件中都用到同一个类型,此时可以创建 .d.ts 文件提供该类型,实现类型共享。
  • 操作步骤:
    1. 创建 index.d.ts 类型声明文件。
    2. 创建需要共享的类型,并使用 export 导出(TS 中的类型也可以使用 import/export 实现模块化功能)。
    3. 在需要使用共享类型的 .ts 文件中,通过 import 导入即可(.d.ts 后缀导入时,直接省略)。
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值