用js编写的项目虽然开发很快,但是维护是成本很高,而且js不报错啊啊啊啊啊!!!
以js为基础进行扩展的
给变量赋予了类型
语法、实战(ts+vue3)
TypeScript 是 JavaScript 的一个超集,支持 ECMAScript 6 标准(ES6 教程)。
TypeScript 由微软开发的自由和开源的编程语言,在 JavaScript 的基础上增加了静态类型检查的超集。
TypeScript 设计目标是开发大型应用,它可以编译成纯 JavaScript,编译出来的 JavaScript 可以运行在任何浏览器上。
转换为js一般用Babel?TSC,一般使用Babel比较多
特点:始于js,归于js,类型校验,适合开发大型项目,拥有js最新的特性
var/let/const 标识符 : 数据类型 = 赋值;
let message:string = "Hello World"
2、类型推导
let message= "Hello World"
会自动推导出类型
不区分整数、浮点数类型,统一都为number类型
let arr = ["abc" , "bdf" ,"scd"]
// 类型推导为string[]
let arr2 :string[] = ["asd","fgh","jkl"]
arr2.push("xcx")
// arr.push(123)
// 泛型的方式来约束
let arr3 : Array = [1,2,3,4,5]
arr3.push(6)
let o : {
name:string,
age:number
} = {
name:"abc",
age:18
}
但是其实这样会不安全
let o = {
name:"abc",
age:18
}
直接这样写就好啦
const sum = ( num1:number , num2:number) => {
return num1 + num2
}
sum(1,2)
如果后面不写类型的话,得到的是any类型
函数的返回值类型是可以推导的,也可以通过以下方式进行定义
const sum = ( num1:number , num2:number) : number => {
return num1 + num2
}
// 匿名函数,最好不要添加对应的类型,一般根据上下文进行推导
const names : string[] =['a','b','c']
names.forEach((item , index , arr) => {
console.log(item , index , arr)
})
type PointType = {
x : number,
y : number
}
const printPoint = (point: PointType) => {
console.log("x坐标",point.x)
console.log("y坐标",point.y)
}
printPoint({x:1 , y:2})
export{}
在属性后面加上一个问号
let id : any = "aaa" //推导出来id是一个string类型
// 但是id有可能使用数字表示的
id = 123 //用了any之后就可以用数字啦
id = {name : "why" , level : 90}
// 但是感觉和js大差不差了
// 可以搞一个联合类型 |
let id2 : string | number = "aaa"
id2 = 123
描述类型不确定的变量
在unknown类型上进行所有的操作都是不合法的
可以使用类型缩小来解决这个问题
let foo:unknown = 123
// foo.toString() //会报错的
if (typeof foo === 'number'){
foo.toString() //类型断言
}
表示函数没有返回值,它的返回值就是void类型
const sum = ():void => {
console.log("sum");
}
sum()
export{}
可以将undefired配置反弹
应用场地:
永远不会发生值的类型,比如死循环或者抛出异常
tuple,通常可以作为返回的值
可以存放多种数据类型,而且明确的知道是什么类型
const info :[string , number , number] = ['张三',120,11]
联合类型:就是用’|'来分隔已有的类型
交叉类型:满足多个条件,一般用于interface,&进行连接
// 交叉类型:同时满足多个类型
interface Fish {
name : string
age : number
}
interface Swim {
sex : string
}
// 交叉类型的使用
type p = Fish & Swim
类型别名:type定义别名
// type取别名
type myNumber = number | string
let id : myNumber = 123
const printId = (id : myNumber) => {
console.log(id)
}
interface:
// 直接声明接口
interface PointType2 {
x : number,
y : number
}
const printPoint = (point : PointType2) => {
console.log(point.x, point.y)
}
大部分情况下两个都是可以的
区别:
接口类型只能够声明对象
type myNumber = number | string
let id : myNumber = 123
在声明对象时,interface可以多次声明
// 直接声明接口
interface PointType2 {
x : number ,
y : number
}
interface PointType2 {
x : number ,
y : number,
z : number
}
// 声明都必须要满足
const point : PointType2 = {
x : 1,
y : 2,
z : 3
}
const printPoint = (point : PointType2) => {
console.log(point.x, point.y)
}
支持继承
interface PointType3 extends PointType2{
r : string
}
类型断言 as :通过类型断言就可以去将类型转换成具体的类型
const imgUrl = document.querySelector('img') as HTMLImageElement
imgUrl.src = "xxx"
// 1、断言只能断言成更加具体或者是不太具体的类型
// const age = 18 as string
const age = 18 as any | unknown
非空类型断言:
interface IPerson {
name : string,
age : number,
friend ?: {
name : string
}
}
const info : IPerson = {
name : '张三',
age : 18,
}
// 访问属性:可选链
console.log(info.friend?.name)
// 属性赋值
// info.friend?.name = '李四' // 报错,因为friend是可选属性,不能赋值
// 解决方式1:类型缩小
if(info.friend){
info.friend.name = '李四'
}
// 解决方式2:非空断言 !(有点危险,确保friend一定有值才可以用)
info.friend!.name = '李四'
类型缩小:限制到一个较小的类型,确定其类型
if (typeof foo === 'number'){
foo.toString() //类型断言
}
平等缩小:===/!==
instanceof
in
const arr : string = "aaa"
// 1、typeof
if(typeof arr === "string"){
console.log("是字符串")
}
// 2、平等缩小,一般用来判断字面量类型
type Direction = "left" | "right" | "up" | "down"
const switchDirection = (direction:Direction) => {
if(direction === "left"){
console.log("向左移动")
}else if(direction === "right"){
console.log("向右移动")
}else if(direction === "up"){
console.log("向上移动")
}else if(direction === "down"){
console.log("向下移动")
}
}
// 3、instanceof
// 传入日期打印当前时间
const getDate = (date : string | Date) => {
if(date instanceof Date){
console.log(date.getDate())
}
}
// 4、in
interface ISwim {
swim : () => void
}
interface IRun {
run : () => void
}
const dog : ISwim = {
swim : () => {
console.log("狗会游泳")
}
}
const move = (animal : ISwim | IRun) => {
if("run" in animal){
animal.run()
}else if ("swim" in animal){
animal.swim()
}
}
move(dog)
字面量类型:
// 定义字面量
type Direction = "left" | "right" | "up" | "down";
const d1 : Direction = "left" //相当于枚举
// const d2 : Direction = "aaa" //报错
type method = "get" | "post" | "put" | "delete";
const request = (url : string , method : method) => {
}
const info = {
url:"xxx",
method:"get"
}
// request(info.url , info.method) //报错:类型“string”的参数不能赋给类型“method”的参数。
// 解决:
const info1 : {url : string , method : method} = {
url:"xxx",
method:"get"
}
const info2 = {
url:"xxx",
method:"get"
}as const
request(info1.url , info1.method) // 正确
request(info2.url , info2.method) // 正确
export{}
函数类型(难点):
// 1、函数类型表达式
// 格式:(参数列表:对应的形参名字加类型) => 返回值
// 起别名
type barType = (num1 : number) => number
const bar : barType = (arg : number):number => {
return arg;
}
// 1、函数类型表达式
// 格式:(参数列表:对应的形参名字加类型) => 返回值
// 起别名
type barType = (num1 : number) => number
const bar : barType = (arg : number):number => {
return arg;
}
// 练习
// 函数中传入函数
type calcFnType = (num1 : number , num2 : number) => number
const calc = (calcFn : calcFnType ) => {
const num1 = 10
const num2 = 20
const res = calcFn(num1 , num2)
console.log(res)
}
const add = (num1 : number , num2 : number) => {
return num1 + num2
}
// 匿名函数
calc((num1 , num2) => {
return num1 - num2
})
calc(add)
export{}
ts对于传入函数类型的多余的参数会被忽略掉
调用签名:指定函数类型的方法
函数本身也是一个对象,函数也会有其他的属性,调用签名就可以声明属性
interface IBar {
name:string
age:number
// 函数可以调用,函数签名
(num1 : number) :number
}
const bar: IBar = (num1 : number) : number => {
return 123
}
bar.age = 18
bar.name = "111"
bar(123)
怎么分辨:
1、如果只是描述函数类型本身(函数可以被调用),使用函数类型表达式
2、如果在描述函数作为对象可以被调用,同时也有其他属性时,使用函数调用签名
构造签名:
class Person {
}
interface ICTPerson {
new () :Person //构造签名
}
const factory = (fn : ICTPerson) =>{
const f = new fn() //any
return f;
}
factory(Person)
// 重载:
// 1、先编写重载签名
function cz(num1 : number , num2 : number) : number
function cz(num1 : string , num2 : string) : string
// 2、编写通用的函数实现
function cz(num1 : any , num2 : any) : any {
return num1 + num2;
}
最好使用联合类型来代替函数重载
this相关的内置工具:
ThisParamenterType:用于提取一个函数类型Type的this参数类型
// 1、ThisParameterType获取函数的this类型
type FooThisType = ThisParameterType
OmitThisParameter:
type PureFooType = OmitThisParameter
// 3、ThisType 不会返回一个转换之后的类型,标记上下文中的this类型(绑定上下文中的this)
如果这个函数类型没有this参数返回unknown
ThisType:
// ThisType:绑定this上下文
interface IState {
name : string;
age: number;
}
interface IStore {
state: IState;
eating: () => void;
running: () => void;
}
const store : IStore & ThisType = {
state: {
name: 'zhangsan',
age: 18
},
eating: function() {
// 如果不使用ThisType,那么this指向的是window对象,将改为this.state.this
console.log(this.name + ' is eating');
},
running: function() {
console.log(this.name + ' is running');
}
}
store.eating.call(store.state);
export{}