Typescript 相比js特有
·类型系统; |
·对象的接口 |
·DOM操作时候需要进行类型断言 |
上面三个实际是类型系统的三处体现 |
·枚举 |
·js中,-号可以强制转换为数值,ts不行 |
所有合法的js都是ts
1、安装
安装进度卡住可以用淘宝镜像 (在后面加 --registry=http://registry.npm.taobao.org)
tsc -v 查看是否安装成功
2、编译并运行TS代码
手动编译 (注意要把ts文件放在项目目录第一级)
设置类型编译后两个文件产生如下区别
//1.ts
//1.js
总结:
创建ts文件->编译ts->运行js
简化复杂的过程:
1、在idea中勾选这个选项
好像不行
1、使用ts-node包
安装
直接用ts-node 1.ts运行文件
常用类型概述
更改类型js会报错 只能在运行后才能发现错误
但是ts就可以在编译时候提示错误
类型注解:
此处number为类型注解,作用:为变量添加类型约束,比如,上述代码中,约定变量age的类型为number(数值类型)
数组类型
推荐下图上面的红框里类型+[ ]的写法,下面的写法存在但是不推荐
let numbers: number[] = [1,3,5]
for (let number of numbers) {
console.log(number);
}
混合类型:
在括号里用竖线隔开多个类型使得数组中可以出现多种类型的变量
类型别名:
当混合类型很长后,每次书写就不方便,此时可以使用别名代替混合类型
常有基础类型综述:
js原有:
原始类型:
number |
string |
boolean |
null |
underfined |
symbol |
对象类型:object:(包括,数组,对象,函数等对象)
ts新增:
联合类型:
自定义类型(类型别名) |
接口 |
元组 |
字面量类型 |
枚举 |
void |
any |
原始类型的基本使用:
函数类型
1、单独指定参数、返回值的类型
函数表达式
2、同时指定参数、返回值的类型:
void类型(js中没有)
使用函数实现某个功能,参数可传也可以不传:
可选参数:在可传可不传的参数名称后面添加?(问号)
注意顺序,可选参数只能排在必选参数后面
对象类型(就是在描述对象的结构)
对象类型的写法 描述对象的属性和方法
let person:{name:string;age:number;sayHi():void}={
name:'jack',
age:19,
sayHi(){}
}
其中sayHi():void 也可以写成sayHi:()=>void
也可以把括号里分号去掉以换行分割属性
let person:{
name:string
age:number
sayHi():void}={
name:'jack',
age:19,
sayHi(){}
}
对象中的可选属性
与前面函数可选参数一样都是加问号
function myAxios(config:{url:string;method?:string}){}
myAxios({
url:''
})
接口
描述对象的类型达到复用的目的
实际上就是将对象名后面的括号单独拿出来写成接口
interface IPerson{
name:string
age:number
sayHi():void
}
let person2:IPerson = {
name:'jack',
age:18,
sayHi() {
}
}
interface(接口)和type(类型别名)的对比:
相同点:都可以给对象指定类型
不同点:接口,只能为对象指定类型。类型别名,不仅可以为对象指定类型,实际上可以为任意类型指定别名。
interface声明如果重名会自动合并属性,而type声明重复则会报错
type IPerson={
name:string
age:number
sayHi():void
}
let person2:IPerson = {
name:'jack',
age:18,
sayHi() {
}
}
接口继承:
当接口之间出现重合部分,为了避免复写,可以直接继承父类重复
interface Point2D {x:number;y:number}
interface Point3D extends Point2D{
z:number
}
let p3:Point3D={
x:1,
y:0,
z:3
}
一个接口继承另外一个接口的含义:这个接口具有父类接口里的所有睡醒和方法
元组类型
当数组中只有两个元素时候,因为数组无法定死数量,所以这时候可以用元组
let position1:[number,number]=[32,8]
let position2:[number,string]=[32,'8']
类型推论:
在Ts中某些场景,类型推论机制会自动识别类型,此时类型注解可以省略不写
并且类型检查和保护机制也存在
发生类型推论的2种常见场景:1声明变量并初始化的时候 2决定函数返回值时候
如果只声明没有初始化推荐还是手动指定类型
函数参数的地方一定要写类型,返回类型可以省略
推荐能省略类型就省略类型,充分利用类型推论机制,提高开发效率
类型断言
由于类型太宽泛,对象无法获取带a标签的href属性值
这时候可以用as关键字来类型断言
const aLink = document.getElementById('link')as HTMLAnchorElement
var href = aLink.href;
另一种方法是在document前面加<>里面写类型
类型可以通过在浏览器里输出标签的对象来查看,也可以直接打比如a标签就是HTML+a的单词类型
字面量类型
思考以下代码,两个变量的类型分别是什么?
let str1 = 'Hello Ts'
const str2 = 'Hello Ts'
我们可以以变量类型的类型声明变量
let str1 = 'Hello Ts'
const str2:'Hello Ts' = 'Hello Ts'
再如我们把数值类型的变量赋给数值
当数值不是18时将会报错
所以不管是字符还是数值等等都可以作为类型出现,他们有一个统一的名字:字面量类型
但这样做有什么意义呢?
使用模式:字面量类型配合联合类型一起使用
使用场景:用来表示一组明确的可选值列表
比如,在贪吃蛇游戏中,游戏的方向的可选值只能是上、下、左、右中的任意一个。
function changeDirection(direction:'up'|'down'|'left'|'riaght'){
console.log(direction)
}
这时候调用函数,就只能填定义好的类型,使得变量参数不会出错
字面量类型指的是js中的任意的字面值,如字符串,数值等等,字面量在ts中也可以作为类型出现,一般与联合类型一起使用,作用是表示一组明确的可选值列表。
枚举类型
枚举的功能类似于字面类型+联合类型组合的功能,也可以表示一组明确的可选值。
枚举:定义一组命名常量。他描述一个值,该值可以是这些命名常量中的一个。
enum Diretion{Up,Down,Left,Right}
function changeDirection(direction:Diretion){
console.log(direction)
}
changeDirection(Diretion.Right)
于是在Ts 中表示一组可选值,我们拥有两种方案:1、字面量+联合类型,2、枚举类型
我们推荐字面量+联合类型的方式,因为这种方式更加直观、简洁、高效
(枚举类型会编译成js中的对象形式,而字面量+联合类型会直接编译)
枚举成员的值以及数字枚举
注意:枚举成员是有值的,默认为:从0开始自增的数值
我们把,枚举成员的值为数字的枚举,称为:数字枚举。
当然,也可以给枚举中的成员初始化值
当给枚举类型中的第一个赋值后,其它值会默认自增
也可以全部赋值
字符串枚举
枚举成员的值是字符串。
注意:字符串枚举必须要为每个成员都设置初始值
枚举的特点及原理:
枚举是Ts为数不多的非JavaScript 类型级扩展(不仅仅是类型)的特性之一。
因为:其它类型仅仅被当做类型,而枚举不仅作为类型,还提供值(枚举成员都是有值的)。
也就是说,其它的类型会在编译为JS代码时自动移除。但是,枚举类型会被编译为JS代码!
编译为js文件后
我们可以发现在ts中的枚举变异后转换为了js中的对象,枚举的成员作为对象的属性,枚举成员的值作为对象属性的值。
any类型
不推荐使用any
原因:使用any会让TypeScript变为AnyScript (失去TS的类型保护优势)
当值为any时,可以对该值任意操作,并且不会有代码提示
比如把对象类型赋给数值类型,不会有任何报错提示
any主要用途在于写代码某些时候不知道要用的类型名称,或是名称很复杂,临时使用,但是还是不推荐
其它隐式具有any类型的情况:
1、声明变量不提供类型也不提供默认值
2、函数参数不加类型
注意:因为不推荐使用any,所以,这两种情况下都应该提供类型!
typeof 操作符
js中提供了typeof操作符,用来在js中获取数据的类型。
实际上,TS也提供了typeof操作符:可以在类型上下文引用变量或属性的类型(类型查询)。
使用场景:根据已有变量的值,获取该值的类型,用来简化类型书写。
let p ={x:1,y:2}
function formatPoint(point:{x:number; y:number})
function formatPoint(point: typeof p){
}
Typescript高级类型
TS中的高级类型有很多,重点学习以下高级类型:
1、class类 Ts在js基础上增加类型注解和新功能(如成员可见性修饰符)
2、类型兼容类型 表示类型之间的关系
3、交叉类型 类似联合类型
4、泛型和keyof 泛型让函数和接口更加通用
5、索引签名类型和索引查询类型
6、映射类型
TypeScript全面支持ES2015中引的关键字,并为其添加了类型注解和其他语法(比如,可见性修饰符等)。class基本使用,如下:
实例属性初始化:
有默认值的属性,可以省略属性类型
class Person {
age: number =10
gender = '男'
}
const p1= new Person()
console.log(p1.gender)
console.log(p1.age)
构造函数
class Person {
age: number =10
gender = '男'
constructor(age:number,gender:string) {
this.age = age
this.gender = gender
}
}
const p1= new Person(18,'女')
console.log(p1.gender)
console.log(p1.age)
class实例方法:
//实例方法
class Point {
x=1
y=2
scale(n:number):void { //void类型括号后面可以省略返回值类型
this.x*=n
this.y*=n
}
}
const p2 = new Point()
p2.scale(10)
console.log(p2.x,p2.y)
类继承
和java一样,类继承有两种方式1 extend(继承父类) 2implements (实现接口)
定义子类的对象拥有父类和本类的方法
class Animal{
move(){
console.log('Moving along!')}
}
class Dog extends Animal {
bark(){
console.log('汪')
}
}
const dog = new Dog()
dog.move()
dog.bark()
结果:
接口:和java差不多
interface Singable {
sing():void
}
class Person1 implements Singable {
sing(){
console.log("明天开学")
}
}
只读修饰符
readonly:表示只读,用来防止在构造函数之外对属性进行赋值。
只读的属性必须要设定默认值,并且readonly只能修饰属性不能修饰方法
接口或者{}表示的对象类型,也可以使用readonly
class Person2 {
readonly age:number =18
constructor(age:number) {
this.age = age
}
}
有readonly修饰的属性不能被其他的方法修改
在使用readonly时最好手动指定属性类型,不然类型自动推断的类型可能不是我们想要的
接口或者{}表示的对象类型,也可以使用readonly