TypeScript学习记录

安装TypeScript

TypeScript安装方式

npm install -g typescript

第一个TypeScript程序

一、手动编译typescript

tsc 文件名

二、自动编译typescript

1). 生成配置文件 tsconfig.json
tsc --init
2). 修改tsconfig.json配置
"outdir": "./js"
"strict": "false"
3). 启动监听服务
终端 --> 运行任务 --> 监视tsconfig.json

三、类型注解

类型注解:一种轻量级的为函数或变量添加约束

  function showAge(num:number){
    return '我今年'+num
  }

四、接口

接口是对象的状态和行为的抽象

  (()=>{
    // 定义一个接口
    interface IPerson{
      firstName:string  
      lastName:string
    }
    function showFullName(person:IPerson){
      return person.firstName+person.lastName
    }
    let person ={
      firstName:'上官',
      lastName:'婉儿'
    }
    console.log(showFullName(person)); 
  })()

五、类

// ts中书写js中的类,演示效果
(function(){
  //定义一个接口
  interface IPerson{
    firstName:string
    lastName:string
  }

  // 定义一个类型
  class Person{
    firstName:string
    lastName:string
    fullName:string
    constructor(firstName:string,lastName:string){
      this.firstName=firstName
      this.lastName=lastName
      this.fullName = this.firstName+'-'+this.lastName
    }
  }
  // 定义一个函数
  function showFullName(person:IPerson){
    return person.firstName+'_'+person.lastName
  }
  // 实例化一个对象
  const person =new Person('诸葛','孔明')
  console.log(showFullName(person));
  
})()

TypeScript常用语法

一、基础类型

1.布尔值

最基本的数据类型,类型为boolean,结果只有true和false

  let flag:boolean = false

2.数字型

TypeScript中的数字和JavaScript中的数字都是浮点数,类型为number,支持二进制、八进制、十进制、十六进制

  let binaryLiteral: number = 0b1010; // 二进制
  let octalLiteral: number = 0o744;   // 八进制
  let decLiteral: number = 8;         //十进制
  let hexLiteral: number = 0xf00d;    //十六进制

3.字符串型

类型为string,用 ’ ’ 或者 " " 表示

  let str1:string='碧玉妆成一树高'
  let str2:string='万条垂下绿丝绦'
  let str3:string='不知细叶谁裁出'
  let str4:string='二月春风似剪刀'
  console.log(`${str1},${str2},${str3},${str4}`);

字符串和数字拼接

// 字符串和数字拼接
  let num:number = 2020
  console.log(str5 + num);

ts中变量一开始定义什么类型就以后修改时只能改为这种类型

4.undefined和null

  let udf:undefined = undefined
  let nul:null = null

undefined和null都可以作为其他类型的子类型,前提是必须关闭tsconfig.json的严格模式

  let num1:number = null
  let num2:number = undefined

5.数组

①定义数组方式1:
语法格式:let 变量名:数据类型 = [value1,value2,value3]

  let arr1:number[] = [1,2,3,4,5,6]

②定义数组方式二:泛型写法
语法格式:let 变量名:Array<数据类型> = [value1,value2,value3]

  let arr2:Array<number> = [7,8,9,10,11]

注:数组类型定义后,里面的数据类型必须和定义时保持一致,否则就会报错,编译也不会通过。

6.元祖

数组定义时,它的类型合格书就已经限定了。
语法格式:let 变量名:[number,string,boolean] = [value1,value2,value3]

  let arr3:[number,string,boolean] = [2.12,'张三',false]

注:数据的类型和个数要和定义时保持一致。

7.枚举

它是对js基本数据类型的补充,枚举中的每个值称为元素,每个元素有自己的编号,编号默认从0开始递增
语法格式:

enum 变量名{ 元素1,元素2,元素3}

示例:

 enum Fruits{
    pear,
    apple,
    orange
  }
  console.log(Fruits[2]);  // orange
  console.log(Fruits.pear);  // 1

当然我们也可以手动去设置编号

 enum Fruits{
    pear = 1,
    apple,
    orange
  }
  console.log(Fruits.pear)  // 1
  console.log(Fruits.orange)  // 3

8.any

当一个数组中存储多个数据,但是数据的类型和个数都不确定,我们可以使用any类型来定义数组
语法格式:let 数组名:any[ ] = [value1,value2,value3]

  let arr:any[] = [99,'青春不常在,抓紧谈恋爱',true]

9.void

在函数声明时,小括号后面使用:void,代表的该函数没有任何返回值
语法格式:

function 函数名()void{
			console.log('')
}

示例:

  function showInfo():void{
    console.log('你好啊,玛卡巴卡');
  }

10.object

定义一个函数,参数和返回值必须是object类型(必须要有返回值)
语法格式:

function 函数名(变量名:object):object{
	console.log(obj)	
	return{对象}						
}		

示例:

function showObj(obj:object):object{
    console.log(obj);
    return{
      name:'张三',
      age:18
    }
}

11.联合类型

表示取值可以为多种类型中的一种
语法格式:

function 函数名(变量名:数据类型1|数据类型2){
    return 变量名.方法()
   }

示例:

function getStr(str:number|string){
    return str.toString()
   }

12.类型断言

告诉编译器,我知道我自己在干什么,也知道自己是什么数据类型
语法格式:
①:<类型>变量名
②:值 as 类型
示例:

function getStr1(str1:string|number){
    if((<string>str1).length){
      return (<string>str1).length
    }else{
      return str1.toString().length
    }
}
function getStr1(str1:string|number){
    if((str1 as string).length){
      return (str1 as string).length
    }else{
      return str1.toString().length
    }
   }

(13)类型推断
当没有明确指定类型时推测出一个类型

let number = 100  // number

二、接口

1.接口是对象的状态和行为的抽象

接口类型的对象:多了或者少了不允许 只读属性readonly 可选属性:?
语法格式:

定义接口
  interface 接口名{
	变量名1:变量数据类型   
	变量名2:变量数据类型
	...
  }
使用接口
  const student:IStudent={
	变量名1:变量值1
	变量名2:变量值2
	...
  }

示例

定义接口
 interface IStudent{
    id:number
    readonly name:string  // 代表此属性为只读,不能修改
    hobby?:string         // 代表此属性是可选属性
    age:number
  }
使用接口  
 const student:IStudent = {
    id:1,
    name:'张三',
    hobby:'打篮球',
    age:18
  }

2.函数类型

给参数列表的每一项规定一个名字和类型
语法格式:

定义接口
 interface 接口名{
	(变量名1:变量类型,变量名2:变量类型):返回值的类型
 }
声明函数
 const 函数名:接口名 = function 变量名1:变量类型,变量名2:变量类型):返回值的类型{
	return 表达式
 }

示例:

定义接口
 interface IFindFunc{
    (source:string,subString:string):boolean
  }
函数中使用
  const search:IFindFunc=function(source:string,subString:string):boolean{
    return source.search(subString) > -1   // 查找source中是否存在subString元素,返回布尔值
  }

3.类类型

定义一个类,可以实现(implements)接口定义的属性和方法

  // 定义一个接口
  interface 接口名{
    属性或方法
  }
  // 定义一个类
  class 类名implements 接口名{
    属性或方法
  }
  // 实例化一个对象

示例:

  //定义一个接口
  interface ISing{
    sing()
  }
  interface IDance{
    dance()
  }
  // 定义一个类
  class Person1 implements ISing{
    sing() {
      console.log('我唱歌贼好听');
    }
  }
  // 实例化一个对象
  const person1 = new Person1()
  person1.sing()

当然,一个类可是实现多个接口

  // 定义接口
  interface ISing{
    sing()
  }
  interface IDance{
    dance()
  }
  // 一个类可以实现多个接口
  class Person2 implements ISing,IDance{
    sing() {
      console.log('我唱歌很好听');
    }
    dance(){
      console.log('我跳舞也好看');
      
    }
  }

一个接口也可以继承多个接口

interface ISingAndIDance extends ISing,IDance{}
  class Person3 implements ISingAndIDance{
    sing() {
      console.log('我唱歌真的很好听');
    }
    dance(){
      console.log('我跳舞也真的很好看');
      
    }
  }

注意:接口与接口之间叫继承(extends),接口与类之间叫实现(implements)

三、类

1.基本示例

类:可以理解为是个模板,通过模板可以实例化对象

 // 定义一个类
  class Student{
    name:string
    age:number
    grade:string

    // 定义构造函数:为了将来实例化对象时直接对属性的值初始化
    constructor(name = '张三',age = 15,grade = '八'){
      this.name = name
      this.age = age
      this.grade = grade
    }
    // 定义实例方法:
    sayHello(str:string){
      console.log(`我叫${this.name},今年${this.age}岁,我已经${this.grade}年级了`,str);
    }
  }
    // 实例化一个对象
  const stu = new Student()
  stu.sayHello('你今年几年级了啊')

2.继承

继承是类与类之间的关系
继承后类与类之间的叫法:
A类继承了B类,此时A类叫子类,B类叫基类
子类---->派生类
基类---->超类(父类)
示例:

  class Person{
    // 定义属性
    name:string
    age:number
    sex:string
    // 定义构造函数
    constructor(name,age,sex){
      this.name = name 
      this.age = age
      this.sex = sex
    }
    // 定义一个方法
    sayHello(str:string){
      console.log(`你好啊${this.name},${str}`);
    }
  }
    // 定义一个类,继承Person
    class Student extends Person{
      constructor(name,age,sex){
       super(name,age,sex) 
      }
      // 可以调用父类中的方法
      sayHello(){
        console.log('我是父类的方法');
        super.sayHello('哈哈')
      }
    }
    // 实例化person
    const person =new Person('张三',18,'男')
    person.sayHello('呵呵')
    
    // 实例化student
    const stu = new Student('李四',18,'女')
    stu.sayHello()

多态

父类型的引用指向了子类型的对象,不同类型的对象针对相同方法产生不同行为

  // 创建父类
  class Language{
    name:string
    constructor(name:string){
      this.name = name
    }
    read(source:number = 0){
      console.log(`我每天学习${source}${this.name}`);
    }
  }
  class English extends Language{
    name:string
    constructor(name:string){
      super(name)
    }
    read(source:number = 5){
      console.log(`我每天学习${source}${this.name}`);
    }
  }
  
  // 实例化父类
  const lan:Language = new Language('语言')
  lan.read()
  // 实例化子类
  const eng:English = new English('英语')
  eng.read()
  
  // 父类类型创建子类的对象
  const eng1:Language = new English('英语')
  eng1.read()
  
  // 该函数需要的参数是Language类型的
  function showLanguage(lan1:Language){
    lan1.read()
  }
  showLanguage(eng1)

类中的成员修饰符

TypeScript 可以使用三种访问修饰符(Access Modifiers),分别是 public、private 和 protected。主要是可以描述类成员的可访问性。

(1)public

public修饰的属性和方法是公有的,可以在任何地方被访问到。

class Person{
    // 设置公有访问  public
    public name:string
    public constructor(name:string){
      this.name = name 
    }
    public sayName(){
      console.log('你好啊'+this.name);
      
    }
  }
  const per = new Person('丽丽')
  console.log(per.name);   // 丽丽
  per.sayName() // 你好啊丽丽
(2)private

修饰的属性或方法是私有的,不能在声明它的类的外部访问,当然子类也无法访问

  class Person{
    // 设置私有访问  private
    private name:string
    public constructor(name:string){
      this.name = name 
    }
    public sayName(){
      console.log('你好啊'+this.name);
      
    }
  }
  class Student extends Person{
    constructor(name:string){
      super(name)
    }
  }
  // 实例化父类
  const per = new Person('丽丽')
  console.log(per.name);  // ts(16,19) TS2341: Property 'name' is private and only accessible within class 'Person'.
  per.sayName()
   
  // 实例化子类  子类也无法访问
  const stu = new Student('嘻嘻')
  console.log(stu.name);  // .ts(24,19)TS2341: Property 'name' is private and only accessible within class 'Person'
  
(3)protected

修饰的属性和方法受保护,与private相似,区别在于子类可以访问

 class Person{
    // 设置受保护的  protected 
    protected name:string
    public constructor(name:string){
      this.name = name 
    }
    sayName(){
      console.log('你好啊'+this.name);
    }
  }
  class Student extends Person{
    constructor(name:string){
      super(name)
    }
    sayHello() {
      console.log('我可以被访问',this.name);
      
    }
  }
  // 实例化父类
  const per = new Person('丽丽')
  console.log(per.name);  // ts(16,19) TS2341: Property 'name' is private and only accessible within class 'Person'.
  per.sayName() // 你好啊,丽丽
  // 实例化子类
  const stu = new Student('嘻嘻')
  stu.sayHello() // 我可以被访问 嘻嘻

readonly修饰符

readonly修饰符,对类中的属性成员进行修饰,修饰后该属性成员无法在外部修改。

  class Person{
    // 定义属性
    readonly name:string
    // 构造函数
    constructor(name:string){
      this.name = name
    }
    sayHello(){
      console.log('你好啊'+this.name);
    }
  }
  // 实例化对象
  const person:Person = new Person('阿辉')
  person.name = '小刘'  // Cannot assign to 'name' because it is a read-only property

类中的方法也无法修改属性成员。
在这里插入图片描述
注意:如果 readonly 和其他访问修饰符同时存在的话,需要写在其后面。

 class Person{
    // 构造函数
    constructor(public radonly name:string){
      this.name = name
    }
    sayHello(){
      console.log('你好啊'+this.name);
    }
  }

存取器

可以让我们有效控制对 对象成员中的访问,通过get 和 set 进行操作

  class Person{
    firstName:string
    lastName:string
    constructor(firstName:string,lastName:string){
      this.firstName = firstName
      this.lastName = lastName
    }
    // 读取器
    get fullName(){
      console.log('get中...');
      return this.firstName + "_" + this.lastName
    }
    // 设置器
    set fullName(val){
      console.log('set中...');
      
      let names = val.split('_')
      this.firstName = names[0]
      this.lastName = names[1]
    }
    
  }
  // 实例化对象
  const person:Person = new Person('上官','婉儿')
  console.log(person);
  console.log(person.fullName);
  // 设置该属性的数据
  person.fullName = '阿里_爸爸'
  console.log(person.fullName);

静态成员

在类中通过static修饰的属性和方法,就叫做静态成员,构造函数不能通过static来修饰
语法格式:类名.静态属性/方法

  class Person{
    static name1:string = '张三' 
    static sayName(){
      console.log('你好啊');
    }
  }
  // 通过类名.静态属性方式访问成员数据
  console.log(Person.name1);
  // 通过类名.静态属性方式来设置成员数据
  Person.name1 = '李四'
  console.log(Person.name1);
  // 通过类名.静态方法方式来设置成员数据
  Person.sayName()

抽象类

包含抽象方法,也可以包含实例方法,抽象类不能被实例化,为了让子类进行实例化及实现内部抽象方法

  abstract class Animal{
    abstract eat()
    // 会报错,抽象方法不能有具体实现
  // console.log('吃');
    // 实例方法
    sayHi(){
      console.log('你好啊');
    }
  }
  // 定义一个子类
  class Dog extends Animal{
    eat(){
      console.log('真好吃');
      
    }
  }
  // 实例化Dog对象
  const dog:Dog = new Dog()
  dog.eat()
  dog.sayHi()

  // 无法实例化抽象类的对象
  // const ani:Animal = new Animal()

四、函数

函数基本语法

语法格式:let 函数名(参数1:数据类型,参数2:数据类型) => 返回值类型 = function(参数1:数据类型,参数2:数据类型):返回值类型{ 函数表达式 }

  // 函数声明,命名函数
  function add(x:number,y:number):number{
    return x + y
  }
  const result = add(4,3)
  console.log(result);
  // 函数表达式,匿名函数
  const reduce = function(x:number,y:number):number{
    return x - y
  }
  const result2 = reduce(4,3)
  console.log(result2);
  // 函数完整写法
  const reduce1:(x:number,y:number) => number = function (x:number,y:number):number{
    return x / y
  }
  const result3 = reduce1(4,3)
  console.log(result3);

可选参数、默认参数和剩余参数

可选参数、默认参数

  // firstName:string='李'  默认参数
  // lastName?:string       可选参数
  const getFullName = function(firstName:string='李',lastName?:string):string{
    if(lastName){
      return firstName + '_' + lastName
    }else{
      return firstName
    }
  }
  console.log(getFullName());

剩余参数
语法格式:…args: 数据类型 [ ]

  function add(a:number,...args: number[]){
    console.log(a);
    console.log(args);
  }
  add(1,5,6,2,4)

函数重载

函数名字相同,函数的参数及个数不同,如果传入非法数据,会提示错误信息

  function add (x: string,y: string): string
  function add (x: number,y: number): number
  function add(x: string| number,y:string | number): string | number{
    if(typeof x === 'string' && typeof y === 'string'){
      return x + y  // 字符串拼接
    }else if(typeof x === 'number' && typeof y === 'number'){
      return x + y  // 数字相加
    }
  }
  console.log(add('上官','婉儿'));
  console.log(add(10,20));

五、泛型

泛型基本用法

在定义接口、类和函数不能确定是什么类型,而是在使用函数、接口、类的时候菜鸟确定数据的类型
语法格式:

  function 函数名<T>(变量名:T,变量名:数据T):T[]{
  }
  调用时
  函数名<数据类型>()

示例:

  function getArr<T>(value:T,count:number):T[]{
    const arr = []
    for(let i = 0;i < count; i++){
      arr.push(value)
    }
    return arr
  }
  const arr1 = getArr<number>(3.1415926,5)
  const arr2 = getArr<string>('我爱你',3)
  console.log(arr1);
  console.log(arr2);
  console.log(arr1[0].toFixed(2));
  console.log(arr2[0].split(''));

多个泛型参数的函数

  function showMessage<K,V>(value1:K,value2:V):[K,V]{
    return [value1,value2]
  }
  const arr = showMessage<string,number>('abc',123.4567)
  console.log(arr);
  console.log(arr[0].split('-'));
  console.log(arr[1].toFixed(2));

泛型接口

在定义接口时,为接口中的属性或方法定义泛型类型,在使用接口时,再指定具体的泛型类型

  interface IBaseCRUD<T>{
    data:Array<T>
    add:(t:T) => T
    getUserId:(id:number) => T
  }
  class User{
    id:number
    name:string
    age:number
    constructor(name:string,age:number){
      this.name = name 
      this.age = age
    }
  }
  class UserCRUD implements IBaseCRUD<User>{
    data:Array<User>=[]
    add(user:User):User{
      user.id = Date.now()+Math.random()
      this.data.push(user)
      return user
    }
    getUserId (id: number):User{
      return this.data.find(user => user.id === id)
    }
  }
  const userCRUD:UserCRUD = new UserCRUD()
  userCRUD.add(new User('jack',20))
  userCRUD.add(new User('tom',25))
  userCRUD.add(new User('lucy',23))
  userCRUD.add(new User('rousi',21))
  console.log(userCRUD.data);

泛型类

类中的属性值类型是不确定的,方法中的参书返回值类型也是不确定的。

  class Add<T>{
    count:T
    add:(a:T,b:T) => T
  }
  const a1:Add<number> = new Add<number>()
  a1.count = 10
  a1.add = function(a,b){
    return a + b
  }
  console.log(a1.add(1,2));
  
  const a2:Add<string> = new Add<string>()
  a2.count = '10'
  a2.add = function(a,b){
    return a + b
  }
  console.log(a2.add('亮亮','真帅'));

泛型约束

如果我直接对一个泛型参数取length属性会报错,因为这个泛型根本就不知道它有这个属性

  interface ILength{
    length:number
  }
  
  function getLength<T extends ILength>(x:T):number{
    return x.length
  }
  console.log(getLength<string>('bilibili'));
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值