ts基本调试操作。
第一种:(了解一下就好)。
第二种:安装库后方便调试。
执行执行下方命令便可。
npm i ts-node -g
npm init -y //生成一个package.json文件
npm i @types/node -D //装一个声明文件
安装好上方三个命令后,可以直接.ts文件。
提示:如果安装s-node太慢,可以尝试使用下方命令安装。
npm i xmzs -g //安装这个xmzs库会 生成mmp命令便于切换语言
npm use //切换到taobao语言
npm i ts-node -g
安装成功后再mmp use切回到npm 语言。
一、什么是TypeScript?
TS是JS的超集,JS有的TS都有。可以理解为TypeScript (代码有明确数据类型)= Type(类型) + JavaScript(代码没有明确数据类型)。
JS属于动态类型的编程语言,边编译边执行,Bug只能在运行到浏览器中才发现。
TS属于静态类型的编程语言,先编译,再执行,在写代码时就发现Bug。
二、类型全解
类型是一系列值及可以对其执行的操作。对于ts类型的值来说,最终是由类型检查器去判断操作是否有效,从而阻止你做无效的操作。
①unknown | any (顶级类型) > ②Object > ③Number | String | Boolean () > ④number | string | boolean() > ⑤1 '阿羡' false > ⑥never
-
unknown 不知道的类型
少数情况下,如果确实无法预知一个值的类型,不要使用any,应该使用unknown。unknown比any更加安全。
unknown类型的值可以比较(==、===、|| 、&&、 ?),可以否定(!),可以使用JS的typeof 和 instanceof 运算符细化。
let a:unknown = 30;
let b = a==='123';
console.log('a',a); //30
console.log('b',b); //false
console.log('js',typeof a === 'number'); //true
let a:unknown = 1;
let b:number = 2;
let c:any = 3;
a = b;
b = c;
b = a; // 会报错,unknown只能赋值给自身 或者是any
let d = a + 10; //会报错
let xian:unknown = {name:"阿羡"};
console.log(xian.name); //会报错,没有办法读任何属性 方法也不可以调用
-
any 任意类型
在TS中,编译时一切都要有类型,如果无法确定类型是什么,默认为any。any类型的值就像常规的JS一样,类型检查器完全发挥不了作用,应该尽量避免使用。any包含所有值,可以对其做任何操作,例如加法,乘法等。
声明变量的时候若没有指定任意类型都默认为any。
-
Object 类型
1、大写的Object
在JS中,所有的类型最终都会指向Objec。在TS中,可以理解为包含所有类型的Object,可以等于任何一个值。
let a:Object = 1213;
let a1:Object = '1213';
let a2:Object = [1213];
let a3:Object = {};
let a4:Object = () => {};
2、小写的object
一般常用于泛型约束,代表一个非原始类型(引用类型)的类型。(原始类型比如数字,字符串,布尔值)(引用类型比如数组,对象,函数)
3、{} 空对象
这个字面量模式它虽然可以赋值任意类型,但是赋值完后,它后面是没办法再做任何修改了的。所以这个类型还是少用比较好。
// let a:{} //可以了解为new Object,也可以支持所有类型
let a:{} = 1213;
let a1:{} = '1213';
let a5:{} = false;
let a2:{} = [1213];
let a3:{} = {};
let a4:{} = () => {};
-
数组类型
// 数组类型
// 写法1(常用)
let arr:boolean[] = [true,false]
// 写法2 数组泛型 规则 Array<类型>
let arr:Array<boolean> = [true,false]
①定义对象数组使用interface时
// 定义对象数组
interface XX{
name:string
age?:number
}
let arrX:XX[] = [{name:"阿一"},{name:"阿二"}]
②定义二维数组
// 二维数组
// 写法1
let arr:number[][] = [[1],[2],[3]]
// 写法2 容易套娃
let arr:Array<Array<number>> = [[1],[2],[3]]
// 多维数组
// 写法1
let arr:number[][][] = [[[23,23]],[2],[3]]
③定义一个数组里面有几种类型时
let arr:any[] = [1,'222',true,{}]
-
函数类型
①关于显示注解返回类型
TypeScript能推导出 函数体中 的类型,但是多数情况下无法推导出 参数的类型,只在少数特殊情况下能根据上下文推导出参数的类型。所以返回值类型能被推导出来,有时可以省略不写。
②函数表达式和箭头函数的写法
③函数默认的参数
④函数可选参数
注意:函数的可选参数和默认参数不能同时设置。
⑤当参数是一个对象时
⑥函数this类型
TS 可以定义this类型,且必须是在第一个参数定义this的类型,在js中不能这样做。
⑦函数重载
多次调用函数,函数的输出类型取决于输入的参数类型。
// 函数重载
let user:number[] = [1,2,3]
// function findNum(add:number[]) //如果传的是一个number类型的数组则做数组追加插入
// function findNum(id:number) //如果传入了id就是单个查询
// function findNum() //没传参,就返回全部
function findNum(ids?:number | number[]){
if(typeof ids == "number"){
return user.filter(v => v==ids)
}else if(Array.isArray(ids)){
user.push(...ids)
return user
}else{
return user
}
}
console.log('没传参,就返回全部',findNum());
console.log('传参,查某个值',findNum(3));
console.log('传参,追加',findNum([4,5,6]));
⑧剩余参数
-
联合类型(符合 ‘|’ 表示)
let phone:number | string = 123; //phone的值既可以是number型也可以是string型
phone = '456';
-
交叉类型(符合 ‘&’ 表示)
类似于继承,两个定义类型接口的属性整合在一起了。
-
类型断言(as)
-
内置对象
// ECMAScript 的内置对象类型的定义
// ECMAScript 的内置对象 Boolean String Number String RegExp Date Error
let num:Number = new Number()
let s:String = new String('阿羡')
let d:Date = new Date()
let reg:RegExp = new RegExp(/\g/);
let error:Error = new Error("错错错")
let xhr:XMLHttpRequest = new XMLHttpRequest()
// DOM 类型的定义
let ss:HTMLElement = document.querySelector('section') //section标签,header标签,footer标签归属于HTMLElement类型
let div:HTMLDivElement = document.querySelector('div')
let inp:HTMLInputElement = document.querySelector('input')
let canvas:HTMLCanvasElement = document.querySelector('canvas')
let ggg:NodeListOf<HTMLDivElement | HTMLElement> = document.querySelectorAll('div footer');
// BOM 类型的定义
let local:Storage = localStorage
let loc:Location = location
let cookie:string = document.cookie
let promise_obj:Promise<number> = new Promise(resolve => resolve(23))
promise_obj.then(res => {
console.log('res',res) //结果输出是23
})
-
元组类型
元组规定了数量、对应位置和对应类型。元组(Tuple)是固定数量的不同类型的元素的组合。
let data: [string, string, number][] =
[
['title', 'name', 1],
['title', 'name', 1],
['title', 'name', 1],
['title', 'name', 1],
['title', 'name', 1],
]
// const arr:readonly[x:number,y?:boolean] = [1]
const arr:readonly[x:number,y:boolean] = [1,false]
// 获取元组的类型
type first = typeof arr[0] //读类型 first = number
type second = typeof arr['length'] //数组的长度 second = 2
-
枚举型
枚举的作用是列举类型中包含的各个值。这是一种无序结构数据,
①数字枚举——默认就是从0开始的 可以不写值
②数字枚举——增长枚举。
如下,我们定义了一个数字枚举, red使用初始化为 1
。 其余的成员会从 1
开始自动增长。
③字符串枚举
④异构枚举
// 枚举可以混合字符串和数字
enum Types{
No1 = "No",
Yes1 = 1,
}
⑤接口枚举
⑥const枚举
⑦反向映射
注意:不会为字符串枚举成员生成反向映射。
-
null类型
null是所有类型的子类型,表示缺少值。
-
undefined类型
undefined是所有类型的子类型,意思是未定义,代表尚未赋值的变量。
-
void类型
void是函数没有显示返回任何值时的返回类型。
void也可以定义undefined 和 null类型。但是null 不能 赋予 void 类型 ,void类型不可以分给其他类型。
//这里void类型,代表这个函数没有返回值
function myFn():void{ }
-
never类型
never是函数永不返回(eg:函数抛出异常,或者永远运行下去,即是死循环)时使用的类型。
三、interface关键字
接口是一种命名类型的方式,这样就不用在行内定义了。
①基础用法
②重名时,叠加(重合)属性
③任意属性(一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集)
④带问号(?)时,可选属性
⑤readonly时(只读,后面不能再修改它的内容,一般用来定义函数和后台数据库返回的id)
⑥接口继承(类似于属性重合)
⑦定义函数类型
// interface 一般用来定义对象的类型
// interface 后面的词名第一个字母要大写
// interface 多行也可以不用逗号隔开
interface Bxx{
phone:string
}
interface Person extends Bxx{ //extends 接口Person继承接口Bxx的属性
name:string
age:number
[propName:string]:any// 任意key,索引签名,其它属性(不止一个)就不会强检验了
value1?:string //加个问号,代表自定义的这个值,使用的时候可有可无
readonly id:number
readonly fn:()=>boolean //该函数返回值类型是布尔值
fn2:() => void //该函数没有返回值
}
interface Person{
hobby:string // interface 遇到重名自定义对象属性,只会叠加(重合)在一起,不会报错
}
const person:Person ={
name:"阿羡",
age:23,
hobby:'singing',
a:1,// 任意key
b:2,// 任意key
id:1,
fn:()=>{
return true
},
fn2:()=>{
console.log('233')
},
phone:'12345678911'
}
// 函数调用
person.fn()
// person.fn = ()=>{return true}
// 定义函数类型
interface Fn{
// (函数参数):返回值的类型
(name:string):number[]
}
const fnn:Fn = function(name:string){
console.log(name)
return [1,2,3]
}
四、type关键字
// 给类型起别名
type s = string
let str:s = "阿羡"
console.log(str); //输出结果是 阿羡
// 定义函数别名
type str1 = ()=>string
let s:str1 = ()=>'我是阿羡'
console.log(s);
//定义联合类型别名
type str2 = string | number
let str22:str2 = 'aaaa'
let str222:str2 = 2222
//定义值的别名
type str3 = boolean | 0 | '阿羡'
let str3333:str3 = true //变量str3333的值 只能是上面value定义的值
str3333 = '阿羡' //变量str3333的值 只能是上面value定义的值
// extends包含,左边的值 会作为 右边类型 的子类型
type a1 = 1 extends number ? 1 : 0 //输出结果是 1
type a2 = 1 extends never ? 1 : 0 //输出结果是 0
type 和 interface
相同点:都可以定义类型。
区别:
- 两个interface可以extend(继承合并),type 只能通过 交叉类型( & ) 合并。
- type 可以定义 联合类型( | ) 和 可以使用一些操作符, interface不行。
- interface 遇到重名的会合并,type 不行。