赞
踩
安装 npm install typescript -g
查看版本 tsc --version
新建ts 文件 (记得导出)
typescript 定义时可指定 变量类型 在名称后面加引号 和 类型
格式为 let 名称: 类型 = 值 (例如: let name:string = ‘张三’)
类型 string 首字母为小写
let message: string = '张三'
console.log(message, '------')
let name = 123
name = 66
export {}
运行 tsc xxxx 并在html中引入
<html>
<head></head>
<body>
<h1>哈哈哈哈</h1>
</body>
<script src="xxxxx"></script>
</html>
在 ts 中不定义 类型 会默认赋值 值的类型
例如 let name = 123 则默认 name的类型是 number
但 使用 const 赋值时 会默认返回 字面量类型
例如 const name = 1.88 则默认 name的类型是 1.88 等同于 const name:1.88 = 1.88
所以:let 推导出来的是通用类型,const推导出来的是字面量类型
Array
//明确的指定<数组>的类型注解:两种写法
// 1.string[]: 数组类型,并且数组中存放的是字符串
let list: string[] = ['张三','李斯']
list.push('王五')
//2. Array<number> 数组类型,并且数组中存放的是number
let arr:Array<number> = [0,1,2]
arr.push(9)
export {}
Object
let info: { name: string age: number } = { name: '青子', age: 18 } console.log(info.name) // 可以通过 type 定义 type infos = { names: string ages: number } let info1: infos = { names: '陆景', ages: 18 } console.log(info1.ages) export { }
使用
// z? 为可传值,不是必传
type obj = {
x: number
y: number
z?: number
}
function getNum(val: obj) {
return val.x + val.y
}
getNum({ x: 1, y: 2 })
export { }
函数的类型
参数
function getInfo(num1:number,num2:number){
return num1 + num2
}
getInfo(5,6)
export {}
返回值
//返回值可以明确指定,也可以自动进行推导
function getInfo(num1:number,num2:number):number{
return num1 + num2
}
let val = getInfo(5,6)
console.log(val)
export {}
匿名参数
const names = ['abc','cds','opp']
//匿名函数最好不要添加注解类型
names.forEach(function(item,index,arr){
console.log(item,index,arr)
})
export {}
使用
type val = {
time: number
text: string
}
function getList(value: string) {
let arr: val[] = []
arr.push({ time: 111, text: '你好' })
return arr
}
let list = getList('oioioio')
list.map(item => {
console.log(item.time, item.text)
})
export {}
any
//any表示不限制任意类型
let id: any = 44
id = "text"
id = []
console.log(id.length)
export { }
unknown
let foo:unknown = 'pp'
foo = 123
//要求必须进行类型的校验
if( typeof foo === 'string'){
console.log(foo.length)
}
export{}
void
// 没有返回值的时候
function foo(num:number,num1:number):void{
console.log(num+num1)
}
export {}
never
// 一般情况下不会使用never ,never表示不会返回任何值 // 封装工具的时候可以使用 function getFoo(message: number | string) { switch (typeof message) { case "string": console.log(message.length) break case "number": console.log(Number(message)) break default: const check: never = message } } getFoo(123) export{}
tuple
//元组类型,元组数据结构中可以存放不同的数据类型,取出来的item也是有明确的类型
const info:[string,number,number] = ['zs',18,1.88]
const value = info[1]
export{}
联和类型的使用
//有的情况下一个值可能是number 也可能是string 类型,这种情况下就可以使用联合类型
let id: number | string = 123
id = 'aaa'
//范围缩小
if(typeof id === 'string'){
console.log(id.length)
}
export{}
类型别名的使用type
// type 类型的别名
type val = number | string
let id: val = '123'
id = 456
export { }
接口声明的使用interface
//type 直接赋值 type info = { x: number y: number z?: number } //interface 声明 interface info1 { x: number y: number z?: number } function getFoo(val:info1){ return val.x + val.y } getFoo({x:1,y:2}) export{}
别名和接口的区别
//区别一:type类型使用范围更广,接口类型只能用来声明对象
type info = number
type info1 = string[]
//区别二 : interface 可以多次声明,可以继承
interface Ikun {
x: number
y: number
}
interface Ikun {
z?: number
}
export { }
交叉类型的使用
//交叉类型,满足两个或多个条件 interface info { name: string, age: number } interface Ikun { running: () => void } type NewType = info & Ikun let list: NewType = { name: '张三李斯', age: 15, running: function () { return '你干嘛!哎哟' } } export {}
类型断言
// 获取DOM 元素 <img calss="img"/>
//使用类型断言
//类型断言规则:断言只能断言成更加具体的类型,或者不太具体(any/unknown)类型
const imgEl = document.querySelector(".img") as HTMLImageElement
imgEl.src = "xxx"
imgEl.alt = 'yyy'
export {}
非空类型断言
interface info { name:string age:18 friend?:{ name:string } } let foo:info = { name:'张三', age:18 } // 访问属性:可选链:?. console.log(foo.friend?.name) // 属性赋值 // 解决方案一:范围缩小 if(foo.friend){ foo.friend.name = '言念' } // 解决方案二:非空类型断言(有点危险,只有在确保friend 一定有值时才能使用 foo.friend!.name = '言念' export{}
字面量类型
type utils = { url: string, method: "post"|"get" }
let request:utils = {url:'xxxx',method:'post'}
request.method as "post"
export {}
类型缩小
//1 typeof type id = string | number let foo: id = "123" if (typeof foo === "string") { console.log(foo.length) } // 2 ===/!== type Direction = "left" | "right" | "top" | "bottom" function switchDirection(direction: Direction) { if (direction === "left") { console.log("左") } else if (direction === "right") { console.log("右") } else if (direction === "top") { console.log("上") } else if (direction === "bottom") { console.log("下") } } // 3 instanceof 传入一个日期,打印日期 function printDate(date: string | Date) { if (date instanceof Date) { console.log(date.getTime()) } else { console.log(date) } } // 4 in 判断是否有一个属性 interface Iswim { swim: () => void } interface Irun { run: () => void } function move(animal: Irun | Iswim) { if ("swim" in animal) { animal.swim() } else if ("run" in animal) { animal.run() } } const fish: Iswim = { swim: function () { } } const dog: Irun = { run: function () { } } move(dog) export { }
函数类型的表示方法
//方案一: 函数类型表达式 function type expression
//格式: (参数列表) => 返回值
type BarType = (num: number) => number
const bar: BarType = (aa: number): number => {
return 123
}
export { }
函数的表达方式
type BarType = (num1: number, num2: number) => number function calc(calcFn: BarType) { const num1 = 10 const num2 = 20 const res = calcFn(num1, num2) console.log(res) } function add(num1: number, num2: number) { return num1 + num2 } calc(add) //匿名函数 calc(function (num1, num2) { return num1 * num2 }) export { }
函数的类型-调用签名
// 1.函数类型表达式 type BarType = (aa: number) => number const bar: BarType = (val: number): number => { return 123 } // 2. 函数的调用签名 interface IBar { name: string age: number //函数可以调用:函数调用签名 (num: number): number } const bar1: IBar = (val: number): number => { return 123 } bar1.name = 'pp' bar1.age = 15 bar1(123) export { }
函数的参数-可选参数
// y?是可选参数 类型为 number | undefined
function foo(x:number,y?:number){
return x
}
foo(10)
export {}
函数的参数-参数默认值
// 函数的参数可以有默认值
// 1. 有默认值的情况下,参数的类型注解可以省略
// 2. 有默认值的参数,是可以接收一个 undefined 的值
function foo(x:number, y=100){
console.log(x)
}
foo(10)
foo(20,undefined)
foo(10,30)
export{}
函数的参数-剩余参数
type val = (string | number)[]
function foo(...ages: val) {
console.log('----')
}
foo(123,'name')
export {}
函数的重载
// typescript 中函数的重载方法
// 1.先编写重载签名
//2 编写通用的函数实现
function add(x: number, y: number): number
function add(x: string, y: string): string
function add(x: any, y: any): any {
return x + y
}
add(10, 30)
add('a', 'r')
export { }
ts中类的基本使用
class Person{
name!: string
age!: number
constructor(name:string,age:number){
this.name = name
this,age = age
}
}
const p1 = new Person('张文',15)
console.log(p1.name,p1.age)
export {}
ts中类的成员修饰符
// public 默认 // private 只能在类中使用 // protected 只能在类中使用,子类也可访问 class Person { protected name: string private age: number constructor(name: string, age: number) { this.name = name this.age = age } private eating() { console.log('吃东西', this.age) } } class tt extends Person { constructor(name: string, age: number) { super(name, age) } yy() { console.log(this.name) } } export { }
ts中类的修饰符readonly
class Person{
readonly name:string
age:number
constructor(name:string,age:number){
this.name = name
this,age = age
}
}
const p = new Person('why',18)
console.log(p.name,p.age)
// p.name = '张三' readonly 只读属性,不能写入
p.age = 20
export{}
ts中类的setter 和 getters
class Person { //私有属性:属性前面会使用_ // 为什么设置私有属性 ,限制不合理的赋值 ,比如年龄 不可能超过 200 ,就可以在set 拦截 private _age :number constructor(age:number){ this._age = age } set age(newValue:number){ if(newValue > 0 && newValue < 200){ this._age = newValue }else{ console.log('你的年龄挺特别!!!') } } get age(){ return this._age } } const p = new Person(20) p.age = 30 console.log(p.age) export {}
ts中类的参数属性的使用
class Person{
// 语法糖
constructor(public name:string){
this.name = name
}
}
const p = new Person('张')
p.name = '离'
export {}
ts中抽象类和方法的使用
//抽象类 abstract class Shape { //getArea 方法只有声明,没有实现体 // 实现体让子类自己实现 // 可以将 getArea 方法定义为抽象方法:方法的前面加 abstract // 抽象方法必须出现在抽象类中,类前面也要加 abstract // 抽象类 不能 实例化 abstract getArea() } // 矩形面积 class jx extends Shape { constructor(public x: number, public y: number) { super() } getArea() { return this.x * this.y } } // 三角形面积 class sjx extends Shape { constructor(public w: number, public h: number) { super() } getArea() { return (this.w * this.h) / 2 } } // 通用函数 function calcArea(shape: Shape) { return shape.getArea() } calcArea(new jx(10, 20)) calcArea(new sjx(8, 10)) export { }
ts中的类型检测-鸭子类型
// TypeScript 对于类型检测的时候使用的鸭子类型
// 鸭子类型:如果一只鸟,走起来像鸭子,游起来像鸭子,看起来像鸭子,那么你可以认为它就是一只鸭子
// 鸭子类型,只关心属性和行为,不关心你具体是不是对应的类型
class Person{
constructor(public name:string, public age:number){}
}
function tt(p:Person){
console.log(p.name,p.age)
}
tt(new Person('zs',20))
tt({name:'44',age:10})
export{}
ts对象类型的修饰符
type info = { name: string age?: number } interface Ikun { chang: string tao: string readonly rap: string } // ? 可选 readonly 只读 let t: info = { name: '张三李四' } let t1: Ikun = { chang: '情人', tao: '练习两年半', rap:'你干嘛!哎哟' } export { }
ts中的接口继承特性
interface XHZ {
name: string
age: number
}
//接口的继承
interface Ikun extends XHZ {
slogan: string
}
let ikun: Ikun = {
name: '蔡徐坤',
age: 18,
slogan: '你干嘛!哎哟'
}
export { }
ts中的接口的类实现过程
interface IKun { name: string age: number playBasketball: () => void } interface IRun { fn: () => void } class Person implements IKun, IRun { name: string age: number playBasketball() {} fn() {} } let IKun2 = new Person console.log(IKun2.name, IKun2.age, IKun2.playBasketball, IKun2.fn) export { }
ts严格字面量赋值检测
interface Iperson { name:string age:number } //奇怪的现象一 const obj = { name:'言念', age:18, height:1.88 } let info:Iperson = obj //奇怪的现象二 function tt(val:Iperson){ } tt(obj) // 解释现象 // 第一次创建的对象字面量,称之为fresh (新鲜的) // 对于新鲜的字面量,会进行严格的类型检测,必须完全满足类型的要求(不能有多余的属性) export{}
ts中的枚举类型
// 枚举默认值为0,向上递增,可以赋值 enum tt { LEFT, RIGHT } enum ttt { LEFT = 'LEFT', RIGHT = 'RIGHT' } let s: tt = tt.LEFT function ss(t: ttt) { if (t === 'LEFT') { console.log('-------') } } ss(ttt.LEFT) export { }
泛型-类型的参数化
// 固定写死类型 function foo(name:string,age:number){ } foo('陆青',18) // 泛型 function IKun<Type>(val:Type):Type{ return val } // 完整写法 let t1 = IKun<number>(111) let t2 = IKun<string>('陆青') let t3 = IKun<{name:string}>({name:'陆青'}) // 简写 let t4 = IKun(111) let t5 = IKun('陆青') let t6 = IKun({name:'陆青'}) export{}
泛型-传入多个类型
function Ikun<Type, Element>(val1: Type, val2: Element) {
return '你干嘛!哎哟'
}
Ikun(10, 20)
Ikun(10, '陆青')
Ikun(10, [1, 2, 3])
export {}
泛型-泛型接口的使用
// 泛型可以赋值默认 type IKun<T = string> = { name:T, age:number, love:T } let kunkun:IKun = { name:'陆青', age:20, love:'打篮球' } let huang:IKun<number> = { name: 10, age:20, love:11 } export {}
泛型-泛型类的使用
class Point<T = number>{
x: T
y: T
constructor(x: T, y: T) {
this.x = x
this.y = y
}
}
const p1 = new Point(1, 3)
const p2 = new Point<string>('1', '3')
export { }
泛型-泛型约束使用
interface ILength { length: number } // getLength 没必要使用泛型 function getLength(arg: ILength) { return arg.length } const p1 = getLength('123') const p2 = getLength(['q', 'w']) const p3 = getLength({ name: 'rr', age: 10 }) // 获取传入的内容,这个内容必须有length属性 // Type 相当于是一个变量,用于记录本次调用的类型,所以整个函数的执行周期中,一直保留着参数的类型 function getInfo<Type extends ILength>(args: Type) { return args } const p4 = getInfo('123') const p5 = getInfo(['q', 'w']) const p6 = getInfo({ name: 'rr', age: 10 }) export { }
泛型-泛型参数的使用约束
//传入key的类型
function getObjectProperty<O, K extends keyof O>(obj: O, key: K) {
return obj[key]
}
// K extends keyof O 等同于 K extends "name"|"age"|"love" keyof获取 info所有key
const info = {
name: '荒',
age: 24,
love: '最爱吃兽奶'
}
const name = getObjectProperty(info, 'name')
export { }
创建一级文件夹 service ,二级文件夹config,request
service > index.ts
import { BASE_URL, TIME_OUT } from './config'
import HYRequest from './request'
const hyRequest = new HYRequest({
baseURL: BASE_URL,
timeout: TIME_OUT
})
export default hyRequest
config > index.ts
// 1 手动切换,有风险 // export const BASE_URL = 'xxxxxx' // export const BASE_URL = 'xxxxxx' // 2 vite默认提供的环境变量 // import.meta.env.MODE console.log(import.meta.env.DEV) // 是否开发环境 console.log(import.meta.env.PROD) // 是否生产环境 console.log(import.meta.env.SSR) // 是否服务器渲染 // 3 新建.env 文件, 可以建多个(列如:.env.development(开发读取) .env.production(生产读取),命名使用VITE_ XXX,加上 .local表示不会提交到git let BASE_URL = '' if (import.meta.env.DEV) { BASE_URL = 'xxxxxx' } else { BASE_URL = 'xxxxx' } console.log(BASE_URL) export { BASE_URL } export const TIME_OUT = 10000
request > index.ts
import axios from 'axios' import type { AxiosInstance } from 'axios' import type { HYRequestConfig } from './type' class HYRequest { instance: AxiosInstance // request 实例 => axios 实例 constructor(config: HYRequestConfig) { this.instance = axios.create(config) //每个instance 都添加拦截器 this.instance.interceptors.request.use( (config) => { console.log('全局请求成功拦截') return config }, (err) => { console.log('全局请求失败拦截') return err } ) this.instance.interceptors.response.use( (res) => { console.log('全局响应成功拦截') return res }, (err) => { console.log('全局响应失败的拦截') return err } ) this.instance.interceptors.request.use( config.interceptors?.requestSuccessFn, config.interceptors?.requestFailureFn ) this.instance.interceptors.response.use( config.interceptors?.responseSuccessFn, config.interceptors?.responseFailureFn ) } //封装网络请求方法 request<T = any>(config: HYRequestConfig<T>) { if (config.interceptors?.requestSuccessFn) { config = config.interceptors.requestSuccessFn(config) } return new Promise<T>((resolve, reject) => { this.instance .request<any, T>(config) .then((res) => { if (config.interceptors?.responseSuccessFn) { res = config.interceptors.responseSuccessFn(res) } resolve(res) }) .catch((err) => { reject(err) }) }) } get<T = any>(config: HYRequestConfig<T>) { return this.request({ ...config, method: 'GET' }) } post<T = any>(config: HYRequestConfig<T>) { return this.request({ ...config, method: 'POST' }) } delete<T = any>(config: HYRequestConfig<T>) { return this.request({ ...config, method: 'DELETE' }) } patch<T = any>(config: HYRequestConfig<T>) { return this.request({ ...config, method: 'PATCH' }) } } export default HYRequest
request > type.ts
import type { AxiosRequestConfig, AxiosResponse } from 'axios'
export interface HYInterceptors<T = AxiosResponse> {
requestSuccessFn: (config: AxiosRequestConfig) => AxiosRequestConfig
requestFailureFn: (err: any) => any
responseSuccessFn: (config: T) => T
responseFailureFn: (err: any) => any
}
export interface HYRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
interceptors?: HYInterceptors<T>
}
在.vue 页面使用
<script lang="ts" setup>
import HYRequest from '../../service'
HYRequest.get({
url: '/home/multidata'
}).then((res) => {
console.log(res)
})
</script>
效果
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。