TypeScript 的使用

138 阅读5分钟

一、 TS开发环境搭建

1.为什么TS的代码可以在浏览器运行?

浏览器只认识JS的代码,所以,用TS语法写出的代码,要编译成JS的代码,才能被浏览器运行。

2.TS怎么样才能进行编译?

  • webpack + babel
  • vite
  • tsc typescript compiler

3.三种编译工具如何使用?

tsc

tsc是运行了直接将ts文件转换成js文件,然后node运行。 这个操作在命令行运行,很难去操作html,就比较麻烦。

运行示例:

//bash
tsc 1.ts
node 1.ts

于是得到1.js的文件

vite

官网:开始 | Vite 官方中文文档 (vitejs.dev)

运行实例:

//bash
yarn create vite 
// 勾选:vue 然后勾选ts
yarn
yarn dev

//改ts文件内容,看html中是否按照预期正常运行

二、TS中如何支持JS中的数据类型呢?

number、string、boolean、symbol、bigint、undefined、null、Object

//ts文件
const a:number = 1
const b:string = '1'
const c:boolean = true
const d:symbol = Symbol('key')
const e:bigint = 1234n
const f:null = null
const g:undefined = undefined 

const h:object = [1,2,3]
const h1 : Object = {}

const i:Array<string>  =['1','2']
const j:Array<number|string|null>  = [1,2,'a',null]

const k0 = (a,b)=> a+b
const k1:Function = (a,b)=> a+b
const k2:(a:number,b:number)=>number = (a,b)=> a+b
const k3 = (a:number,b:number):number=> a+b
type K4 = (a:number,b:number)=>number
const k4:K4  = (a,b) => a+b
interface AddWithProps{
    (a:number,b:number):number,
    fuck : string
}
const k5:AddWithProps = (a,b)=>a+b 
k5.fuck = 'fuck'
console.log(k5(1,2),k5.fuck);

三、TS中有哪些JS中没有的类型?

any、unknown、void、never、Enum(枚举)、元组

//ts文件
const app:any = '1'
app.name

const banana:unknown  = JSON.parse("{'name':'Yuyuan'}")
type Ba = {
    name : string
}
type Ban = {
    age :  number
}
console.log((banana as Ba ).name);
console.log((banana as Ban).age);
//as的意思是断言,我就说banana的类型是Ba,你就按照Ba给我来使用

const car:(a:number,b:number )=>void = function(a,b){
    console.log(a,b);
}
car(1,2)

type D = number & string
const dark:D 
//D 是一个空集,也就是类型nerver,于是不能给dark赋值,无法初始化
type Des = 1 | 2 |3 | undefined
let destination:Des 
switch (destination){
    case 1 :
        break
    case 2 :
        break
    case 3 :
        break
    case undefined :
        break
    default : 
        console.log(
            destination
        )
        break
    //default 的情况就是never
}

enum El {
   东,南,西,北
}
const element:El =  El.东
console.log(element);


const fly:[number,string] = [1,'a']
  • 在TS中,class既是一个值,又是一个类型
//TS文件
class A{}
const a = A
const b : A = {}

四、TS中的组合类型:交叉类型和联合类型

  • 交叉类型:&
  • 联合类型:|

联合类型比交叉类型理解起来要简单。 联合类型的理解就是,多种类型中只能取一种类型; 交叉类型是多种类型取合并类型;如果类型中有冲突,就无法合并。

联合类型:|

//TS文件
type A = {
    name : 'yuyuan',
    age : number
}
type B = {
    name : 'yuyuanOne',
    gender : string
}
const fun = (a:A|B)=>{
    if(a.name === 'yuyuan'){
        a.age
    }else{
        a.gender
    }
}

交叉类型:&

//TS文件

//只有'a'是不冲突的,所以交叉起来只能取'a'
type A1 = 'a' | 'b' | 'c'
type B1 =  'a' | 1 | 2
type C1 = A1 & B1
const del:C1 = 'a' 

//A3 和 B3 没有冲突,所以可以合并,如果改name:boolean,那么A3&B3 === never
type A3 = {
    name : string,
    age : number
}
type B3 = {
    name : '',
    gender : string
} 
const f1 = function(a:A3&B3){
    a.age,a.gender,a.name
} 

五、如何声明一个div(dom)的类型?

//TS文件
const div:HTMLDivElement = document.getElementnById('fuck')

按住ctrl,单击类型,就能查看所有的dom的类型

六、什么是泛型?

关于泛型,直接理解就是广泛的类型

    1. 与泛型的最早接触
    • 我们使用泛型来指定,数组中的每一项都是什么类型
    • 于是我们得到,泛型的符号表示是<>
 const a: Array<string> = ['f','u','c','k']  
    1. 如何理解泛型
    • 借助函数的概念来理解泛型是比较方便且准确的
    • 泛型为输入的变量x,而申明的类型则代表类型的映射规则
//类型Fns代表映射类型的规则,T=> T
type Fns<T> = (a:T,b:T) => T
//因为T是泛型,所以,可以是number,也可以是string,等等类型
const fn1:Fns<number> = (m,n) => m+n
const fn2:Fns<string> = (m,n) => m+n
    1. 多层泛型
    • 我们可以按照函数来理解泛型,同样可以安装按照来使用泛型

image.png

image.png

七、重载是用来干嘛的?

重载是为了满足一个函数的各个参数的不同使用需求而设定的

  • 举个例子:

    • fn(a,b)
    • 如果a,b都是数字,那么返回a+b
    • 如果a,b都是字符串,那么返回 a +''+b
  • 泛型无法在声明前使用

    • 于是用泛型我们只能这样
    • fn1+fn2无法对传入参数的类型进行判断,然后条件返回
    • fn3你如何对传入的参数进行检查呢?
type Fnc<T> = (a:T,b:T)=> T
const fn1 :Fnc<number> = (a,b)=> a+b
const fn2 :Fnc<string> = (a,b)=> a+''+b 


const fn3 :Fnc<number|string> = (a,b)=> {
    if(typeof(a) === "number" && typeof(b) === 'number' ){
        return a+b
    }else if(typeof(a) === "string" && typeof(b) === 'string' ){
        return a+''+b
    }else{
        throw new Error('input error')
    }
}
//fn3的缺陷:只有运行后才会报错,那我用TS干嘛?还不如用js
fn(1,'a')
  • 如何实现重载?
    • 写function,不要用泛型!!!!
    • 先把函数可能的参数类型组合都写出来
    • 最后写函数的函数体的时候,类型写any,然后对参数类型进行判断然后使用
function fn(a:number,b:number):number 
function fn(a:string,b:string):string
function fn(a:any,b:any):any{
    if(typeof(a) === "number" && typeof(b) === 'number'){
        return a+b
    }else{
        return a+''+b
    }
}

七、如何用泛型封装网络请求库?

现实情况往往是复杂的

image.png

type User = {
    id : string | number ,
    name : string ,
    age:number,
    else : Object
}

type CreateSource =(path:string)=>{
    create : (attr:Partial<(Omit<User,'id'>)>) => Promise<User>;
    update: (id:User['id'],attr:Partial<(Omit<User,'id'>)>) => Promise<Response>;
    delete : (id:User['id'])=>Promise<Response>;
    get : (id:User['id'])=>Promise<User>;
    getPage : (page:number)=>Promise<[User]>;
}

const createSource:CreateSource = (path)=>{
    return {
        create(attr){
        const url = path+'s'
            return axios.post<User>(url,{data:attr})
        },
        updated() {
            
        },
        delete(){

        },
        get(){},
        getPage(){

        }
    }
}

var useSource = createSource('/api/v1/user')