为什么要学习typescript?
对JavaScript的增强
- 可以提供类型标注 大大的增强的代码的可读性与可维护性
- 提供不断发展的JavaScript特性 可以让我们编写出更加健壮的代码
未来前端发展的趋势
在未来前端应用会越来越复杂,ts是特别适合开发大型复杂项目的。现在几大前端主流框架对TS的兼容性越来越好 , Vue3 React Angular
技术转型的优势
现在很多公司招聘要求上会写着要求掌握一门或者多门前端语言,JS肯定是基础,如果你也会TS的话,现在来说,这个肯定是优势,未来TS绝对是趋势
提升个人能力与竞争力
因为JS是弱类型动态语言,大型项目中使用JS最后会遇到各种各样的问题,掌握了TS开发技巧的话,对于个人成长是非常好的
TypeScript快速入门
先来看两段代码
const hello = (a,b) => a + b //JS代码
const hello = (a:number,b:number):number => a+b//TS代码
可以看到,这两个函数的功能都是一样的,实现一个相加的函数。理想情况下,我们调用hello(1,2)能得到我们想要的结果,但是万一我们参数输入错误了呢???????比如hello(1,'ere'),JS写的代码在这种情况下依然能得到结果,是一个字符串,但这个是我们想要的结果吗???nonono , TS写的代码在这种情况下就会报错,这就体现出了TS的优势了,你参数定义的什么类型,传进去的参数就应该是什么类型
Object 类型
所有非原始类型的数据类型都是,Object类型
let foo : object = function(){}
let foo1 : object = []
let foo2 : object = {}
//——————————————————————
let foo : {foo : number} = {foo:23} //这种直接赋值的方法格式是:声明了多少变量,那么就应该实例化多少个对象
let foo1 : {foo : number} = {foo:23,age:'2324'} //这个就会报错
TypeScript数据类型之基础类型
数字,字符串,布尔值
let bool:boolean = false//true
let number:number = 2021
let number1:number = 0b10101//支持二进制
let number2:number = 0x744//支持八进制
let number3:number = 0xf00d//支持16进制
let str:string = 'zhoujing'
数组
TypeScript像JavaScript一样可以操作数组元素。 有两种方式可以定义数组。 第一种,可以在元素类型后面接上 [],表示由此类型元素组成的一个数组
let arr1 : Array<number> = [1,2,3]//数组泛型
let arr2 : number[] = [1,2,3]
元组 Tuple
元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。 比如,你可以定义一对值分别为 string和number类型的元组。
let tuple:[string,number,boolean];
tuple = ['zhoujing',25,true] //ok
tuple = [25,'zhoujing','haha'] //incorrect
枚举 enum
enum类型是对JavaScript标准数据类型的一个补充。 像C#等其它语言一样,使用枚举类型可以为一组数值赋予友好的名字。
enum Slolar{
sun = 0,
earth,
moon,
triton
}
enum Solar{
sun ,
earth,
moon,
triton
}
使用枚举很简单:通过枚举的属性来访问枚举成员,和枚举的名字来访问枚举类型 , 我们接触到比较多的可能是数字枚举,sun值为1,后面的值没有赋值的话,就会依次自增长 , 如果没有初始值,枚举对象的第一个值就会赋值为0
null与undefined
TypeScript里,undefined和null两者各自有自己的类型分别叫做undefined和null。 和 void相似,它们的本身的类型用处不是很大
let u: undefined = undefined;
let n: null = null;
官方文档是鼓励使用-- strictNullChecks,这个是在tsconfig.json文件里面
接口 interface
接口就是用来约束对象的条件,只起一个约束的作用,实际运行中并没有实际意义,在这里同时引入可选成员,只读成员,动态成员
interface inter{
name : string
inner?:string//可选成员
readonly outer : number //
}
const host : inter = {
name : 'zhoujing' ,
inner : 'dfdf',
outer : 1212//只读成员初始化之后不能修改
}
interface cache{
[name:string]:string//动态类型,不知道到底有多少子项
}
const ca:cache={}
ca.bar = 'defe'
ca.foo = 'foo'
类 class
传统的JavaScript程序使用函数和基于原型的继承来创建可重用的组件,但对于熟悉使用面向对象方式的程序员来讲就有些棘手,因为他们用的是基于类的继承并且对象是由类构建出来的。 从ECMAScript 2015,也就是ECMAScript 6开始,JavaScript程序员将能够使用基于类的面向对象的方式
class Person{
name : string //在使用前必须声明
age : number
constructor(name:string,age:number){
this.name = name
this.age = age
}
sayHi(msg:string):void{
console.log(`i am ${this.name}`)
}
}
与es6相比,TS定义类如果是构造函数里面使用的变量需要提前声明一下
继承
class Animal {
move(distanceInMeters: number = 0) {
console.log(`Animal moved ${distanceInMeters}m.`);
}
}
class Dog extends Animal {
bark() {
console.log('Woof! Woof!');
}
}
const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();
访问修饰符
class Person{
public name : string //默认都是public
private age : number //私有属性只能在内部访问
protected gēnder : string
constructor(name:string,age:number){
this.name = name
this.age = age
}
sayHi(msg:string):void{
console.log(`i am ${this.name}`)
console.log(this.age)
}
}
class Student extends Person{
constructor(name:string,age:number){
super(name,age)
console.log(this.gender)//protected只允许在子类中使用
}
}
const tom = new Person('tom',25)
console.log(tom.age)//error
总结来说,TS类声明的对象默认都是public,加不加public修饰符没啥影响,加了private修饰符之后,对象只能在内部访问了,加了protected修饰之后,只能在派生子类使用
只读属性
你可以使用 readonly关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化。
class Person{
public name : string //默认都是public
private age : number //私有属性只能在内部访问
protected gender : string
readonly sex : string //只读属性必须在声明时或者构造函数中初始化
constructor(name:string,age:number){
this.name = name
this.age = age
this.gender = 'male'
this.sex = 'female'
}
sayHi(msg:string):void{
console.log(`i am ${this.name}`)
console.log(this.age)
}
}
readonly属性必须在声明时或者构造函数中初始化,两者选其一,不能两个同时操作,初始化之后不管是内部还是外部都是不能改变的
抽象类
抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。 不同于接口,抽象类可以包含成员的实现细节。 abstract关键字是用于定义抽象类和在抽象类内部定义抽象方法。
抽象类一般是需要当作继承使用,需要在子类中继承与实现,抽象类中有抽象方法时,子类必须继承
abstract class Aniaml{
eat(food : string):void{
console.log(`呼噜呼噜吃:${food}`)
}
//父类有抽象方法时,子类必须继承实现
abstract drink(water:string):void
}
class Cat extends Aniaml{
drink(water: string): void {
// throw new Error("Method not implemented.")
console.log('dwdwd')
}
}
//这里父类定义了drink方法,所以子类必须继承实现
泛型 Generics
当我们参数类型不确定时,可以使用泛型,这样就不用重复定义函数
//当你不知道你传递的是什么类型之的时候使用范型
function createArray1 (number :number,value:number) :number[]{
return Array(number).fill(value)
}
function createArray2 (number:number,value:string): string[]{
return Array(number).fill(value)
}
function createArray<T> (number :number,value:T) : T[]{
return Array<T>(number).fill(value)
}
const arr = createArray<string>(4,'number')
const arr1 = createArray<number>(4,3)