TypeScript入门笔记

TypeScript

1、介绍
1、typescript是有微软开发的一款开源的编程语言
2、typescript是JavaScript的超集,遵循最新的ES6、ES5规范。typescript扩展了JavaScript的语法
3、本质上这个语言添加了可选的静态类型和基于类的面向对象编程,通俗的理解为JavaScript的一个特殊版本,其语法规范严谨,适用于开发大型项目应用
4、谷歌也在大力支持typescript的推广,谷歌的angular2.x就是基于typescript
5、最新的vue、react也可以集成typescript
6、nodeJS框架的Nextjs、midway中用的就是typescript

官网:https://www.tslang.cn/

2、ts安装、编译、运行
2.1、安装
npm i typescript -g

注意:在只用npm命令之前一定要保证电脑中已经安装了node

2.2、运行
tsc demo.ts
2.3、自动编译

1、生成配置文件

创建tsconfig.json文件

tsc --init

修改配置文件

// ①创建js文件夹
// ②在tsconfig.json中
"outDir": "./js",

2、运行

第一种方式:点击终端——>运行任务——>typescript——>tsc:监视tsconfig.json

第二种方式:在项目文件夹中调出终端窗口,执行以下命令

tsc -p tsconfig.json --watch
3、ts数据类型

typescript中为了使编写的代码更规范,更有利于维护,增加了类型校验,在typescript中主要为我们提供了以下的数据类型

3.1、布尔类型(boolean)
var flag:boolean = true
flag = false
// flag = 123   // 错误
console.log(flag)
3.2、数字类型(number)
var num:number = 123
num = 456
// num = "str"  // 错误
console.log(num)
3.3、字符串类型(string)
var str:string = "web前端"
str = "hahaha"
// str = 123  // 错误
console.log(str)
3.4、数组类型(array)
// 第一种定义方式
var arr1:number[] = [1,2,3,4]
console.log(arr1)
// 第二种定义方式
var arr2:Array<number> = [1,2,3,4,5]
console.log(arr2)
// 第三种定义方式
var arr3:any[] = [1,"str",true]
console.log(arr3)
3.5、元数组(tuple)
var arr4:[number,string,boolean] = [11,"web前端",true]
3.6、枚举类型(enum)

随着计算机的不断普及,程序不仅只用于数值计算,还广泛地用于处理非数值的数据。比如:性别、月份、颜色

// 标识符未赋值
enum sex{
  man,
  woman
}
var s1:sex = sex.man
var s2:sex = sex.woman
// 如果标识符没有赋值,他的值就是下标
console.log(s1) // 0
console.log(s2) // 1

// 标识符赋值了
enum method{
  get = "哈哈哈,get",
  post = "哈哈哈,post"
}
var m1:method = method.get
var m2:method = method.post
console.log(m1) // 哈哈哈,get
console.log(m2) // 哈哈哈,post
3.7、任意类型(any)
var ss:any = 123
ss = "str"
ss = true
console.log(ss) // true
3.8、对象类型(object)
var obj:object = {x:10,y:20}
console.log(obj)
3.9、null和undefined
var n:number | undefined
console.log(n)

var nu:null = null
console.log(nu)

var a:number | null | undefined
a = 123
console.log(a)
3.10、void类型

在typescript中的void表示没有任何类型,一般用于定义方法的时候没有返回值的情况

function fn():void{
  console.log("123")
}
fn()
3.11、never类型

是其他类型的子类型,表示从不会出现的值

var nev:never
// nev = true  // 错误的写法
nev=(()=>{
  throw new Error("错误")
})()
4、ts函数
4.1、函数定义
// 函数声明法
function fn1():string{
  return "我是fn函数"
}
// 匿名函数
var fn2 = function():number{
  return 123
}
4.2、传参
// 传参
function getInfo(name:string,age:number):string{
  return `我的名字是${name}---我的年龄是${age}`
}
console.log(getInfo("张三",123))

// 没有返回值的方法
function fn3():void{
  console.log("我是fn3函数")
}
fn3()
4.3、默认参数

es5里面没法设置默认参数,es6和ts中都可以设置默认参数

// es5里面没法设置默认参数,es6和ts中都可以设置默认参数
function add1(a:number,b:number=50):number{
  return a+b
}
add1(10)
4.4、可选参数

es5里面方法的实参和形参可以不一样,但是ts中必须一样,如果不一样需要配置可选参数

function add2(a:number,b?:number):number{
  if(b){
    return a+b
  }else{
    return a
  }
}
add2(10)

注意:可选参数必须配置到参数的最后面

4.5、剩余参数
function fn4(parent:string,...child:string[]){
  console.log(parent) // 优就业
  console.log(child)  // ["web", "UI", "java", "python"]
  console.log(parent+":" + child.join("-"))  // 优就业:web-UI-java-python
}
fn4("优就业","web","UI","java","python")
4.6、ts函数重载

java中方法的重载:重载指的是两个或者两个以上同名函数,但他们的参数不一样,这是会出现函数重载的情况。typescript中的重载:通过为同一个函数提供多个函数类型定义来实现多种功能的目的。 ts为了兼容es5以及es6重载的写法和java中有区别

function getInfo1(name:string):string;
function getInfo1(name:string,age:number):string;
function getInfo1(name:any,age?:any):any{
  if(age){
    return "我叫:"+name+"我的年龄是:"+age
  }else{
    return "我叫:"+name
  }
}
4.7、箭头函数 es6
let fn5 = (a:number,b:number):number=> a+b
5、类
5.1、定义类

属性要加数据类型,方法的参数和返回值也要加数据类型

class Person1{
  name:string   // 属性
  constructor(name:string){  // 构造函数   实例化类的时候触发的方法
    this.name = name
  }
  getName():void{
    console.log("我是:" + this.name)
  }
}
let p1 = new Person1("张三")
console.log(p1.name)    // 张三
p1.getName()  // 我是:张三
5.2、继承类
class Man extends Person1{
  sex:string = "男"
  constructor(name:string){
    super(name)
  }
  getName():void{
    super.getName()
    console.log("我的性别是:" + this.sex)
  }
}
let p2 = new Man("李四")
console.log(p2.name)  // 李四
console.log(p2.sex) // 男
p2.getName()  // 我是:李四  我的性别是:男
5.3、属性修饰符
public   类内、子类、类外都可以使用
protected  类内、子类可以使用,类外不能使用
private  类内可以使用,子类、类外不能使用
默认是publice,在任何一个地方都可以使用
class Car{
  public name:string
  constructor(name:string){
    this.name = name
  }
  say():void{
    // 类内
    console.log(111,this.name)
  }
}
class Bus extends Car{
  speed:number
  constructor(name:string,speed:number){
    super(name)
    this.speed = speed
  }
  say(){
    // 子类
    console.log(222,this.name)
  }
}

let car1 = new Car("玛莎拉蒂")
// 类外
console.log(car1.name)  // 玛莎拉蒂
car1.say()  // 111 "玛莎拉蒂"

let car2 = new Bus("电动公交车",60)
console.log(car2.name)   // 电动公交车
console.log(car2.speed) // 60
car2.say()  // 222 "电动公交车"
5.4、static

静态方法或静态属性只能类本身调用

class Util{
  static PI = Math.PI
  static getRandom(max:number,min:number):number{
    return Math.floor(Math.random()*(max-min)+min)
  }
}
console.log(Util.PI)  // 3.141592653589793
console.log(Util.getRandom(50,20))  // 44
5.5、抽象类
1、多态

父类点翻译一个函数不去实现,让继承他的子类去实现 每一个子类有不同的表现

class person{
  name:string
  constructor(name:string){
    this.name = name
  }
  eat(){    // 具体吃什么  不知道。   具体吃什么让继承他的子类去实现,每一个子类的表现不一样
    console.log("我是吃的方法")
  }
}
class ZhangSan extends person{
  constructor(name:string){
    super(name)
  }
  eat(){
    return this.name + "吃麻辣烫"
  }
}
class LiSi extends person{
  constructor(name:string){
    super(name)
  }
  eat(){
    return this.name + "吃麻辣小龙虾"
  }
}
2、抽象类和派生类

typescript中的抽象类:他是提供其他类继承的基类,不能直接被实例化。用abstract关键字来定义抽象类和抽象方法,抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。abstract抽象方法只能在抽象类里面。

// 抽象类
abstract class Animal{
  public name:string
  constructor(name:string){
    this.name = name
  }
  abstract eat():any  // 抽象方法不包含具体实现并且必须在派生类中实现
  run(){
    console.log("哈哈哈")
  }
}
// 派生类
class Dog extends Animal{
  constructor(name:any){
    super(name)
  }
  // 抽象类的子类必须实现抽象类里面的抽象方法
  eat(){
    console.log(this.name + "吃狗粮")
  }
}
let d = new Dog("哈士奇")
console.log(d.name)   // 哈士奇
d.eat()   // 哈士奇吃狗粮

class Cat extends Animal{
  constructor(name:any){
    super(name)
  }
  eat(){
    console.log(this.name + "吃猫粮")
  }
  run(){}
}
let c = new Cat("小花猫")
console.log(c.name)   // 小花猫
c.eat()   // 小花猫吃猫粮
6、接口

作用:在面向对象的变成中,接口是一种规范的定义,他定义了行为和动作的规范,在程序设计里面,接口起到一种限制和规范的作用。行为和动作的规范,对批量方法进行约束

6.1、属性类接口

就是传入对象的约束

interface FullName{
  firstName:string;     // 注意使用;结束
  secondName:string;
}

function printName(name:FullName){
  console.log(name)
}

// printName("123")   // 错误

var obj1 = {    // 传入的参数必须包含firstName 和 secondName
  firstName:"张",
  secondName:"三",
  age:18
}
printName(obj1)

可选属性

interface FullName1{
  firstName:string;
  secondName?:string;
}
function getName(name:FullName1){
  console.log(name)
}
getName({
  firstName:"firstName"
})

案例,封装ajax

interface Config{
  type:string;
  url:string;
  data?:string;
  dataType:string
}

function ajax(config:Config){
  var xhr = new XMLHttpRequest();
  xhr.open(config.type,config.url,true);
  xhr.send(config.data)
  xhr.onreadystatechange = function(){
    if(xhr.readyState==4 && xhr.status==200){
      if(config.dataType=='json'){
        console.log(JSON.parse(xhr.responseText))
      }else{
        console.log(xhr.responseText)
      }
    }
  }
}

ajax({
  type:"get",
  url:"https://cnodejs.org/api/v1/topics",
  data:"",
  dataType:"json"
})
6.2、函数类接口

对方法传入的参数以及返回值进行约束

interface encrypt{
  (key:string,value:string):string
}

var md5:encrypt = function(key:string,value:string):string{
  return key+value
}
console.log(md5('name','张三'))

var shal:encrypt = function(key:string,value:string):string{
  return key+"---"+value
}
console.log(shal('name',"李四"))
6.3、可索引接口

对数组、对象的约束。

// 对数组的约束
interface UserArr{
  [index:number]:string
}
var arr:UserArr = ['aaa','bbb','ccc']
console.log(arr[0])
// 对对象的约束
interface UserObj{
  [index:string]:string
}
var obj2:UserObj = {
  name:'张三',
  age:'18'
}
console.log(obj2.name)
6.4、类类型接口

对类的约束,和抽象类有点相似

interface Animal1{
  name:string;
  eat(string:string):void
}

class Dog1 implements Animal1{
  name:string
  constructor(name:string){
    this.name = name
  }
  eat(){
    console.log(this.name + "吃狗粮")
  }
}
var d1 = new Dog1("哈士奇")
console.log(d1.name)    // 哈士奇
d1.eat()  // 哈士奇吃狗粮
6.5、接口扩展

接口可以继承接口

interface Animal2{
  eat():void;
}
interface Person2 extends Animal2{
  work():void;
}
// implements 继承,要求了继承的东西必须要重写
class Web implements Person2{
  name:string;
  constructor(name:string){
    this.name = name
  }
  eat(){
    console.log(this.name + "喜欢吃海底捞")
  }
  work(){
    console.log(this.name + "喜欢敲代码")
  }
}
var w = new Web("张三")
console.log(w.name) // 张三
w.eat() // 张三喜欢吃海底捞
w.work()  // 张三喜欢敲代码

接口扩展和继承结合案例

interface Animal3{
  eat():void
}
interface Person3 extends Animal3{
  work():void
}
class Web1{
  name:string;
  constructor(name:string){
    this.name = name
  }
  coding(code:string){
    console.log(this.name+code)
  }
}
class Web2 extends Web1 implements Person3{
  constructor(name:string){
    super(name)
  }
  eat(){
    console.log(this.name+"喜欢吃海底捞")
  }
  work(){
    console.log(this.name+"敲代码")
  }
}

var w2 = new Web("李四")
console.log(w2.name)    // 李四
w2.eat()    // 李四喜欢吃海底捞
w2.work()   // 李四喜欢敲代码
7、泛型
7.1、泛型定义

在软件工程中,我们不仅要创建一致定义良好的API,同时也要考虑可复用性。组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。

通俗理解:泛型就是解决类、接口、方法的复用性,以及对不特定数据类型的支持(类型校验)

function getData1(value:number):number{
  return value
}
function getData2(value:string):string{
  return value
}
// 造成了代码冗余。我们可以使用any来解决,any放弃了类型检查,传入什么返回什么
7.2、泛型函数

可以支持不特定的数据类型。要求:传入的参数和返回的参数类型一致

// T表示泛型,具体什么类型是调用这个方法的时候决定的
function getData3<T>(value:T):T{
  return value
}
getData3<number>(123)
getData3<string>("123")
// getData3<string>(123)    // 错误
7.3、泛型类
class MinClass<T>{
  list:T[]=[]
  add(value:T):void{
    this.list.push(value)
  }
  min():T{
    var minNum = this.list[0]
    for(var i = 0; i < this.list.length; i++){
      if(minNum > this.list[i]){
        minNum = this.list[i]
      }
    }
    return minNum
  }
}
var mm1 = new MinClass<number>()    // 实例化类,并制定了类的T代表的类型是number
mm1.add(11)
mm1.add(4)
mm1.add(15)
mm1.add(20)
console.log(mm1.min())
7.4、泛型接口
// 第一种方式
interface ConfigFn1{
  <T>(value:T):T
}
var getData4:ConfigFn1 = function<T>(value:T):T{
  return value
}
getData4<string>("张三")
// getData4<number>("123")    // 错误
// 第二种方式
interface ConfigFn2<T>{
  (value:T):T
}
function getData5<T>(value:T):T{
  return value
}
var myGetData:ConfigFn2<string> = getData5
myGetData("20")
// myGetData(20)    // 错误
7.5、将类作为泛型参数
// 定义操作数据库的泛型类
class MysqlDb<T>{
  add(info:T):boolean{
    console.log(info)
    return true
  }
  updated(info:T,id:number):boolean{
    return true
  }
}
// ①定义User类和数据库进行映射
class User{
  username:string | undefined;
  pasword:string | undefined;
}
var u = new User()
u.username = "张三";
u.pasword = "123456"
var Db = new MysqlDb<User>();
Db.add(u)

// ②定义Cate类和数据库进行映射
class Cate{
  title:string | undefined;
  desc:string | undefined;
  status:number | undefined;
  constructor(params:{
    title:string | undefined;
    desc:string | undefined;
    status?:number | undefined;
  }){
    this.title = params.title;
    this.desc = params.desc;
    this.status = params.status
  }
}

// 增加操作
var aa = new Cate({
  title:"分类111",
  desc:"我是分类111",
  status:1
})
// 类当做参数的泛型类
var Db1 = new MysqlDb<Cate>();
Db1.add(aa)

// 修改操作
var bb = new Cate({
  title:"分类222",
  desc:"我是分类222"
})
bb.status = 0
var Db2 = new MysqlDb<Cate>();
Db2.updated(bb,12)
8、模块化
8.1、模块化的概念
1、我们可以把一些公共的功能单独抽离成一个文件作为一个模块。
2、模块里面的变量、函数、类等默认是私有的,如我们想要在外部访问模块里面的数据(变量、函数、类),我们需要通过export暴露模块里面的数据。
3、暴露后我们通过import引入模块就可以使用模块里面暴露的数据。
8.2、模块导出的几种方式

注意:因为现在所有的浏览器都不支持export和import,我们预览效果可以通过webpack打包或者nodeJS环境预览效果。在文件夹中调出终端——>node 文件名

①export导出声明
// 在db1.ts中
export function getData():void{
  console.log("getData被调用")
}
export function save():void{
  console.log("save被调用")
}
// 在db2.ts中
import {getData,save} from "./db1"
getData()
save()
②export导出语句
// 在db1.ts中
function getData():void{
  console.log("getData被调用")
}
function save():void{
  console.log("save被调用")
}
var dbUrl = "我是一段话"
export{
  getData,
  save,
  dbUrl
}
// 在db2.ts中
import {dbUrl,getData,save as sa} from "./db1"
console.log(dbUrl)
getData()
sa()
③export default

export defult默认导出,每个模块都可以有一个default导出。默认导出使用default关键字标记;并且一个模块只能有一个defaul导出。需要使用一种特殊的导入形式来导入default导出。

// 在db1.ts中
function save(){
  console.log("save被调用")
}
export default save
// 在db2.ts中
import aaa from "./db1"
aaa()
④同时使用export和export default引入模块
// 在db1.ts中
export function getData(){
  console.log("getData被调用")
}
var dbUrl = "我是一段话"
export default dbUrl
// 在db2.ts中
import dbUrl,{getData} from "./db1"
console.log(dbUrl)
getData()
9、命名空间
概念:在代码量较大的情况下,为了避免各种变量名冲突,可将相似功能的函数、类、接口等放置到命名空间内
命名空间和模块的区别:
	命名空间:内置模块,主要用于组织代码,避免命名冲突。
	模	块:ts的外部模块简称,侧重代码的复用,一个模块里可能会有多个命名空间。
namespace A{
  interface Person{
    name:string;
    eat():void
  }
  
  export class Zhang implements Person{
    name:string
    constructor(name:string){
      this.name = name
    }
    eat(){
      console.log(`${this.name} 在吃麻辣烫`)
    }
  }
  
  export class Li implements Person{
    name:string
    constructor(name:string){
      this.name = name
    }
    eat(){
      console.log(`${this.name} 在吃麻辣小龙虾`)
    }
  }
}

namespace B{
  interface Person{
    name:string;
    eat():void
  }
  
  export class Zhang implements Person{
    name:string
    constructor(name:string){
      this.name = name
    }
    eat(){
      console.log(`${this.name} 在吃麻辣烫222`)
    }
  }
  
  export class Li implements Person{
    name:string
    constructor(name:string){
      this.name = name
    }
    eat(){
      console.log(`${this.name} 在吃麻辣小龙虾222`)
    }
  }
}

var cc = new B.Li("李四")
console.log(cc.name)
cc.eat()
10、装饰器
装饰器 就是一个函数,是一种特殊类型的声明,他能够被附加到类声明、方法、属性或参数上,可以修改类的行为。
10.1、装饰器声明方式
①普通装饰器(无法传参)
function logClass(params:any){
  // params 就是当前类
  console.log(111,params)
  params.prototype.apiUrl = "动态扩展的属性"
  params.prototype.run = function(){
    console.log("我是一个run方法")
  }
}

@logClass
class HttpClient{
  constructor(){

  }
}
var http = new HttpClient();
console.log(http)
②工厂方式(可以传参)
function logClass1(params:string){
  return function(target:any){
    console.log(111,params) // "http://www.ujiuye.com/api"
    console.log(222,target) // 当前类
    target.prototype.apiUrl = params
  }
}
@logClass1("http://www.ujiuye.com/api")
class HttpClient1{
  constructor(){

  }
}
var http1 = new HttpClient1()
console.log(333,http1)
10.2类装饰器
①普通装饰器(无法传参)
function log1(obj:any){
  console.log(obj)
  obj.prototype.money = 500000
}

@log1
class H1{
  money:number | undefined
}
let h1Child = new H1()
console.log(h1Child.money)  // 500000

@log1
class H2{
  money:number | undefined
}
let h2Child = new H2()
console.log(h2Child.money)  // 500000
②工厂方式(可以传参)
function log2(num:number){
  return (obj:any)=>{
    console.log(num)
    console.log(obj)
    obj.prototype.money = num
  }
}

@log2(200)
class H3{
  money: number | undefined
}
let h3Child = new H3()
console.log(h3Child.money)  // 200

@log2(800)
class H4{
  money:number | undefined
}
let h4Child = new H4()
console.log(h4Child.money)  // 800
10.3属性装饰器
function log3(str:string){
  return(obj:any,prop:any)=>{
    console.log(111,str)  // 就是传递的参数
    console.log(22,obj)     // 要装饰的那个类
    console.log(333,prop)    // 属性的名字
    obj[prop] = str
  }
}
class H5{
  @log3("优就业")name:string | undefined
  @log3("北京")city:string | undefined
}
let h5Child = new H5()
console.log(h5Child.name)   // 优就业
console.log(h5Child.city)   // 北京
10.4方法装饰器
function log4(str:string){
  return (target:any,methodName:any,methodInfo:any)=>{
    console.log(111,str)    // "优就业web前端"
    console.log(222,target)      //  类的构造函数
    console.log(333,methodName)      // 方法名字
    console.log(444,methodInfo)      // 方法的详细信息
    target.run = function(){
      console.log("我是run方法")
    }
  }
}
class H6{
  @log4("优就业web前端") say(){
    console.log("我是H6的方法")
  }
}
let h6Child = new H6()
h6Child.run()   // 我是run方法
10.5方法参数装饰器
function log5(params:any){
  return (target:any,methodName:any,paramsIndex:any)=>{
    console.log(111,params)   // 我是一句话
    console.log(222,target)    // 类的构造函数
    console.log(333,methodName)    // getData
    console.log(444,paramsIndex)    // 参数在列表中的索引
    target.apiUrl = params
  }
}
class H7{
  url:any | undefined;
  constructor(){

  }
  getData(@log5("我是一句话")uId:any){
    console.log(uId)
  }
}
let h7Child = new H7();
h7Child.getData(123456)   // 123456
console.log(h7Child.apiUrl)   // 我是一句话
10.6装饰器执行顺序

属性装饰器——>方法装饰器——>方法参数装饰器——>类装饰器

如果有多个同样的装饰器,他会先执行后面的

function logClass2(params:string){
  return (target:any)=>{
    console.log("类装饰器2")
  }
}
function logClass3(params:string){
  return (target:any)=>{
    console.log("类装饰器3")
  }
}
function logAttrBute2(params?:string){
  return function(target:any,attrName:any){
    console.log("属性装饰器2")
  }
}
function logAttrBute3(params?:string){
  return function(target:any,attrName:any){
    console.log("属性装饰器3")
  }
}
function logMethod2(params?:string){
  return function(target:any,methodName:any,methodInfo:any){
    console.log("方法装饰器2")
  }
}
function logMethod3(params?:string){
  return function(target:any,methodName:any,methodInfo:any){
    console.log("方法装饰器3")
  }
}
function logParams2(params?:string){
  return function(target:any,methodName:any,desc:any){
    console.log("方法参数装饰器2")
  }
}
function logParams3(params?:string){
  return function(target:any,methodName:any,desc:any){
    console.log("方法参数装饰器3")
  }
}

@logClass2("http://www.ujiuye.com")
@logClass3("web前端")
class HttpC{
  @logAttrBute2()
  @logAttrBute3()
  apiUrl:string | undefined
  constructor(){

  }
  @logMethod2()
  @logMethod3()
  getData(){
    return true
  }
  setData(@logParams2()attr1:any,@logParams3()attr2:any){

  }
}
var https:any = new HttpC();
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值