企业网站推广案例,品牌推广计划,wordpress安装插件提速,镇江关键字优化公司文章目录 一、认识TS1.1 JS 存在的问题1.2 TS的出现1.3 TS运行环境运行ts的三种方式 1.4 变量声明1.5 类型推断 二、数据类型2.1 JS数据类型(1) 数组Array(2) 对象Object(3) 其他类型 2.2 TS特有数据类型(1) any类型(2) unknown类型(3) void类型(4) never (了解)(5) tuple类型 … 文章目录 一、认识TS1.1 JS 存在的问题1.2 TS的出现1.3 TS运行环境运行ts的三种方式 1.4 变量声明1.5 类型推断 二、数据类型2.1 JS数据类型(1) 数组Array(2) 对象Object(3) 其他类型 2.2 TS特有数据类型(1) any类型(2) unknown类型(3) void类型(4) never (了解)(5) tuple类型 三、语法细节3.1 可选类型3.2 联合类型3.3 type与interface(1) 类型别名 type(2) 声明接口 interface(3) 区别 3.4 交叉类型3.5 类型断言as3.6 字面量类型3.7 类型缩小 (Type Narrowing) 一、认识TS
1.1 JS 存在的问题
JS没有类型检测。
function getLength(str){return str.length;
}
console.log(getLength(abc)); // 正确调用结果是3
console.log(getLength(123)); // 错误的调用结果是undefined第五行代码在编写时不会报错但是在运行过程中可能会出现TypeError: Cannot read property length of undefined这类的错误。这是因为JS并不会对函数传入的参数进行限制所以这个问题只会在运行时才被发现。进而影响后续代码的执行
所以没有类型监测带来的问题
代码不够安全、不够健壮。没有类型约束那么需要对别人传入的参数进行各种验证来保证我们代码的健壮性我们去调用别人的函数对方没有对函数进行任何的注释我们只能去看里面的逻辑来理解这个函数需要传入什么参数 返回值是什么类型
1.2 TS的出现
TypeScript官网TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
TypeScript是拥有类型的JavaScript超集它可以编译成普通、干净、完整的JavaScript代码。
TS是加强版的JS具有以下特点
JavaScript所拥有的特性TypeScript全部都是支持的紧随ECMAScript的标准所以ES6、ES7、ES8等新语法标准它都是 支持的TS增加了类型约束不必考虑兼容性问题。TS最终会被编译成JS代码编译时可以通过tsc或babel将其转为js始于JS归于JS
1.3 TS运行环境
在.ts文件里编写TS不会出错但是编译时需要搭建对应的环境将其编译为JavaScript才能够在浏览器上运行。
# 全局安装最新版本的 ts
npm install typescript -g# 检查版本查看是否安装成功
tsc --version运行ts的三种方式
(1) 方式一 第一步 tsc 1.hello.ts ; 编译ts文件生成1.hello.js文件 第二步运行.js文件 每次修改完文件后都要单独执行命令进行编译然后再运行。很麻烦。
(2) 方式二
webpack配置(用脚手架创建文件的时候都会配置好这里不细说)
(3) 方式三
通过ts-node库 (接下来学习用这种方式来运行ts文件)。
# 安装ts-node
npm install ts-node -g
# 安装ts-node需要的两个依赖包tslib和types/node
npm install tslib types/node -g
# 运行ts文件这种方式也不需要每次修改完之后单独执行命令进行编译直接执行即可
ts-node hello.ts注意在使用ts-node运行代码时控制台报错Cannot find module ‘./hello.ts’
解决方法添加export {}
// hello.ts
let message: string hello world
console.log(message)
export {}博客使用ts-node命令运行ts文件时报错
1.4 变量声明
声明了类型后TypeScript就会进行类型检测声明的类型可以称之为类型注解Type Annotation
(指明数据类型就是添加类型注解)
var/let/const 标识符数据类型 赋值将变量message声明为string类型
let message:string hello
message 123 // 将其他类型赋值给message会报错:不能将类型number分配给类型string1.5 类型推断
类型推断声明一个变量时如果直接进行赋值 会根据赋值的类型推导出变量(标识符)的类型注解。
let nametom // 推导出name的类型为string
name123 // 这句赋值操作会报错不能将“number”分配给类型string
let num 123const msg 123 // 推导出msg的类型为字面量类型123
const test:HelloHello // 这里Hello 也是字面量类型注
let声明的变量进行类型推导推导出来的是通用类型(number、string之类的)const声明的变量进行类型推导推导出来的是字面量类型
二、数据类型
TS是JS的一个扩展原来JS拥有的东西TS都有包括JS里的八种数据类型TS也是可以使用的。 接下来演示一下如何使用各种数据类型进行数据注解。
2.1 JS数据类型
(1) 数组Array
指定数组的类型注解有两种写法
(1) string:[]——数组类型并且数组里只能存string类型数据
const msg:string[][123,345,567]
msg.push(hello)(2) Arraystring——泛型写法
const names :Arraystring[tom,jerry]
names.push(876) // 会报错简写就是
const name [tom,Lily,张三]
name.push(jerry)
name.push(123) // 会报错(2) 对象Object
info对象的类型就是红框里的样子
明确指定为对象类型的完整写法为:
const info:{name:string,age:number
}{name:tom,age:18
}还有一种写法info:object{...}缺点是不能读取对象内的属性
(3) 其他类型
number类型
// number数据类型ts与js一致不区分整数和浮点数
let num 6.66;
num tom // 会报错
// ES6新增的各个进制的表示方法ts也适用
num 10; // 十进制
num 0b110; // 二进制
num 0o555; // 八进制
num 0xf23; // 十六进制boolean类型
let flag true
flag 20 // 会报错string类型
const name tom
// ts也可使用ES6的模板字符串来拼接变量和字符串
const info my name is ${name}null与undefined类型
// 完整写法
let n:null null
let u:undefined undefined
// 简写
let n null
let u undefined2.2 TS特有数据类型
(1) any类型
在某些情况下无法确定某些变量的类型且该变量的类型可能会发生改变时可采用any类型。
let id:any 987
id tom
id {name:why,age:10}
// 若需定义一个数组,但不确定元素类型可定义为any
const infos:any[] [123,123,{}]这样其实是回归到原始的js了。
应用场景
如果对于某些情况的处理过于繁琐不希望添加规定的类型注解或者在引入一些第三方库时缺失了类型注解这个时候我们可以使用any。
(2) unknown类型
与any作用类似在不确定类型的情况下也可以声明为unknown类型区别是
unknown类型的变量不允许进行任何操作
let num:any123
num 123
console.log(num123); // any类型数据不报错let result:unknowntom
result 123 // 将number类型数据赋值给result不会报错
console.log(result.length); // 读取length属性报错因为不确定result的什么类型读取length可能会出错所以unknown类型数据不允许进行任何操作。
若想进行操作则必须进行类型校验:
let result:unknowntom
result 123
// 必须进行类型校验(类型缩小)才能根据缩小之后的类型进行对应的操作
if (typeof result string) {console.log(result.length);
}(3) void类型
当一个函数没有return返回值的时候其返回值就是void类型
// 未指明返回值类型默认
function printID(id:string){console.log(id);
}明确指明返回值类型是void
function printID(id:string):void{console.log(id);return undefined // 对于返回值为void类型的函数可以return undefined;// return 123 会报错不能将number类型分配给void类型
}(了解)基于上下文类型推导的函数推导出返回类型是void时并不会强制函数一定不能返回内容 但如果是自己编写的函数明确指定是void类型图片里13行的代码则会报错
(4) never (了解)
never 表示永远不会发生值的类型。开发中很少定义never类型。
应用场景 进行类型推导时可能会自动推导出never类型
function handleMsg(msg:string | number){switch(typeof msg){case string:console.log(msg.length);break;case number:console.log(msg10);break;default:const check msg // const check: never}
}msg只可能是string或number类型default语句不可能被执行到所以check被推导为never类型。
(5) tuple类型
tuple元组类型。元组数据结构可以存放不同的数据类型取出来的item也是有明确的类型
const msg:(string|number)[][tom,123,456]
const name msg[0] // name类型是string|number不能明确const info:[string,number,boolean][why,18,true] // 元素的类型应与声明的一一对应比如第二个必须是number类型的数据否则报错
const value info[2] // value类型是booleantuple和数组的区别 数组中通常建议存放相同类型的元素不同类型的元素是不推荐放在数组中。元组中每个元素都有自己特定的类型根据索引值获取到的值可以确定对应的类型
元组类型的应用在函数中使用最多尤其是函数的返回值中
// 将函数会返回值声明为tuple类型
function useState(initialValue:any):[number,(newValue:number)void]{
let stateValue initialValue
function setValue(newValue:any){stateValue newValue
}
return [stateValue,setValue]
}
const [count,setCount] useState(10)
count() // 这行代码会报错count类型是number错误的使用会及时提醒
setCount(100)但若未明确指定返回值的类型则推导为any类型的数组 此时count()语句不合法但没有错误提示则代码是不安全的。
三、语法细节
3.1 可选类型
可以指定某个对象中某个属性是否是可选的可以不传语法就是加个问号?
function printPoint(point: { x: number; y: number; z?: number }) {console.log(point.x)console.log(point.y)console.log(point.z)
}// printPoint({ x: 123}) // 报错因为y是必传的但没传
printPoint({ x: 123, y: 321 }) // 123 321 undefined
printPoint({ x: 123, y: 321, z: 111 }) // 123 321 1113.2 联合类型
TS中我们可以使用运算符从现有类型中构建新类型
联合类型(Union Type)有两个或更多其他类型组成的新类型表示变量类型可以是这些类型中的任意一个。
// foo可以是number类型也可以是string类型
let foo : number | string abc
foo 123给一个联合类型的变量赋值只要保证是联合类型中的某一个类型的值即可。拿到值之后最好需要进行类型缩小判断出更具体的数据类型再进行下一步的操作。
function printId(id:string|number){// 类型缩小if (typeof id string) {console.log(id是,id.toUpperCase());}else {console.log(id是,id);}
}
printId(123) // id是123
printId(tom) // id是TOM3.3 type与interface
(1) 类型别名 type
某些类型名字很长且在多处使用可以给该类型起一个别名。
比如
type IDtype number | string
function printId(id:IDtype) {...}
//等价于
function printId(id:number | string) {...}再比如
type PointType {x:number,y:number,z?:number
}
function printPoint(point: PointType) {...}
// 等价于
function printPoint(point: {x:number,y:number,z?:number}) {...}起别名之后可读性会更强一点使用也更方便一点。
(2) 声明接口 interface
interface的作用和type相似都可以用来 给对象类型起别名。interface的使用方式为
// 通过接口interface 创建某种对象类型----是一种声明的方式
interface PointType{x:number,y:number,z:number}
// 别名type创建某种对象类型----是一种赋值的方式type PointType {x:number,y:number,z:number
}接口的几乎所有特性都可以在 type 中使用。
(3) 区别 一、type类型的使用范围更广接口类型只能用来声明对象 type MyNumber number
type IDtype number | string二、声明对象时interface可以多次声明 type不允许有两个相同名称的别名 type PointType {x:numbery:number
}
type PointType { // 提示标识符PointType重复z:number
}interface可以多次声明同一个接口 interface PointType{x:numbery:number
}
interface PointType{z:number
}
// 这几次声明里的条件该类型的变量都需要满足
const point:PointType{x:20,y:20,z:40
}三interface支持继承 interface IAnimal{name:string,age:number
}
interface IDog extends IAnimal{color: string
}
// 变量dog需要给这三个属性都赋值
const dog: IDog{name:tom,age:2,color:red
}四、interface可以被类实现(涉及到TS面向对象) class Person implements IAnimal{}总结从代码的扩展性角度来说如果是对象类型的声明应使用interface非对心类型的定义应使用type。
3.4 交叉类型
联合类型值为多个类型中的一个即可
交叉类型需要同时满足多个类型的条件使用
type MyType string number 上述代码的含义是MyType类型的变量既是string又是number不可能存在这样的数据所以交叉类型通常是对对象类型进行交叉的
interface IMan{name:string,age:number
}
interface ICoder{name:stringcoding:()void
}
type NewType IMan ICoder
const obj: NewType{name:tom,age:23,coding(){console.log(coding);}
}3.5 类型断言as
在确定具体类型时直接使用类型断言来指明类型减少类型缩小代码的编写。
// 当选择标签选择器时ele和ele2的类型是确定的
const ele document.querySelector(div) // const ele: HTMLDivElement
const ele2 document.querySelector(img) // const ele2: HTMLImageElement
ele2.src... //且可以给src属性赋值// 采用类选择器时,ele3的类型则是const ele3: Element没那么具体了
const ele3 document.querySelector(.img)
ele3.src // 会报错提示Element不存在属性src如果我们确定ele3一定是HTMLImageElement类型则可以使用断言来具体类型
const ele3 document.querySelector(.img) as HTMLImageElement
ele3.src // 断言之后也不会报错TypeScript只允许类型断言转换为 更具体 或者 不太具体 的类型版本
// 代码本身不正确,不建议这样写。这里是为了说明应断言为更加具体或不太具体的类型
const age:number 18
const age1 age as any // 断言为不太具体的类型 number-any
const age2 age1 as string // 断言为更具体地类型 any-string
console.log(age2.length);// number断言为string类型会报错
const age3 age as string3.6 字面量类型
字面量类型literal types
// const类型的变量可自动推断为字面量类型 let也可以声明字面量类型的变量
const name tom // name类型为tom
let name2:tom tom // name2类型为tom
// 字面量类型的应用通常是将多个字面量类型联合
type Direction left | right | up | down
const d1: Direction left案例
const info{url:xxx,method:GET
}
function request(url:string,method:GET|POST){console.log(url,method);
}request(info.url,info.method) // 会报错原因method的类型是string值是GET而request函数要求参数method的类型是GET或者POST
解决
// 方案一类型断言
request(info.url,info.method as GET)// 方案二直接让info对象类型是一个字面量类型
const info{url:xxx,method:GET
} as const
request(info.url,info.method)为什么xxx也可以因为xxx本身是一个string不懂
3.7 类型缩小 (Type Narrowing)
类型缩小有以下几种方式typeof、平等缩小(,!)、instance of、in、等。。 typeof function printId(id:number|string){if (typeof id string) {console.log(id.toUpperCase());}else{console.log(id);}
}平等缩小 ,主要用于字面量类型 type Direction left | rightfunction turnDirection(direction:Direction){switch(direction){case left:console.log(left); break;case right:console.log(right); breakdefault:console.log(调用默认方法); }}instanceof 检查是否为另一个值的实例 function printValue(date: Date | string) {if (date instanceof Date) {console.log(date.toLocaleDateString());}else{console.log(date);}
}if语句里也可以用typeof, 但是 typeof date Date 是不对的; Date 属于object 可以写成typeof date object in用于确定对象是否具有某个属性