一、 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的类型
六、什么是泛型?
关于泛型,直接理解就是广泛的类型
-
- 与泛型的最早接触
- 我们使用泛型来指定,数组中的每一项都是什么类型
- 于是我们得到,泛型的符号表示是
<>
const a: Array<string> = ['f','u','c','k']
-
- 如何理解泛型
- 借助函数的概念来理解泛型是比较方便且准确的
- 泛型为输入的变量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
-
- 多层泛型
- 我们可以按照函数来理解泛型,同样可以安装按照来使用泛型
七、重载是用来干嘛的?
重载是为了满足一个函数的各个参数的不同使用需求而设定的
-
举个例子:
- 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
}
}
七、如何用泛型封装网络请求库?
现实情况往往是复杂的
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')