ts 概略

资源

各种进阶资源 + 联系方式请看下方链接
资源

仅本人笔记所用 想系统学习请移步官网
学习TS的时候可以创建一个新的文件夹 下载ts的npm全局包 来通过编写完ts后 通过 tsc编译一下 编译成为js看里面的原理
TS定义多种类型
  1. 定义字符串类型 let str: string = ‘Yee’
  2. 定义数字类型 let age: number = 30
  3. 定义数组类型有两种方式 以下是定义数组中只能是数字的方式
//1. let list : number[] = [1,2,3]
//2. let list : Array<number> = [1,2,3]
元组
let x : [string,number ]
x = ['hello',10] 这样写是可以的 如果里面的反过来就不行了 也可以 x[0].toString调用字符串的方法 
也可以x[ 3 ] = 'yee' 给一个不存在的赋值(只有ts3.0版本之前可以这样做 之后就不行了 通过不了编译) 但是不能赋不是定义的string number这两种之外的值 
枚举
enum Color {
   Red = 1,
   Green = 3,
   Blue = 5
 } 
 let colorName: string = Color[2]
 console.log(colorName) // Green
 枚举默认从零开始 也可以自定义 比如这里都自定义第一个为1 如果后面不写的话就默认从1开始 后面两个是2,3 可以通过 Color.Green来获取 3 也可以通过color[2]来反查
any:如果不清楚是什么类型 以及不需要类型检查的时候可以定义为any类型
void:通常情况下一个函数没有返回值的时候给这个函数赋 void的类型
function warnUser(): void{
   console.log('this is a ')
 }
 上面的可以给函数赋void的类型 通常情况下 let unusable:void = undefined 这种是没有意义的 而且void也只能赋 undefined 和 null
null 和 undefined的类型也是null和undefined 它们是所有类型的子类型 可以赋值给所有的类型 只要不是通过严格模式的编译都可以通过
never 通常给异常函数使用
function error(message:string): never{
  throw new Error(message)
}
function fail(){
  return error('something failed')
 }
 function inifiniteloop() :never{
   while ( true){ //无限循环的函数也可以使用nevers
   }
  }
联合类型的使用

declare function create(o: object | null) : void;
上述语句的意思是 declare声明 一个函数 它的参数是object类型或者 null类型 它的返回值是void(没有返回值)

create(o:{prop: 0})
create(o:null)
上面两种都是对的
create(o:42)这种就不行了
如果非常确定一个值是什么类型 可以强制转化(类型断言)
let someValue: any = 'this is a string' 
let strLength: number = (<string>someValue).length
let strLength: number = (someValue as string).length
以上两种方法都是强制把someValue变量转为string类型

接口

在ts里面通常通过interface 定义一个接口
在接口中有些属性不是必须的 但是通过interface定义之后如果没有标名是可选属性且没有这个属性的传入那么是会报错的 这个时候都用到可选属性了 例:
interface Square{
  color: string
  area: number
}
interface SquareConfig{ 后加?代表可选类型
  color?: string
  area?: number
}
function createSquare(config: SquareConfig): Square{
  return newSquare //这个返回值必须跟Square中对应上
}
let mySquare = createSquare(config:{color:'black'}) //这里不传area也可以 因为它是可选属性
设置只读属性 只在属性创建的时候可以做修改
interface Point{
  readonly x: number //这里 readonly就是只读属性的设置
  readonly y: number
}
let p1: Ponit = { x: 10,y: 20}
p1.x = 5 //这里就会报错了 因为只读属性不能重新赋值

通过ReadonlyArray可以对数组做只读类型的定义 不过也可以使用as 做改变
函数接口类型
interface SearchFunc {
   (source:string,substring:string):boolean
}
let mySearch:SearchFunc
mySearch = function(src,sub){
  let result = src.search(sub)
  return result>-1
 }
 //也可以指定数组的索引签名 例如
 interface NumberDictionary {
    [index: number]: string
     
     length: number 
     name: string
  }
  let myArray: NumberDictionary = ['ALICE','BOD'] //这个时候通过 myArray = 'Mallory' 不会报错 但是如果赋值为number类型的 就会报错了
类类型与继承
  1. 类 与 接口 都可以继承类 通过extends 继承 和通过implements都可以 具体可以查询里面的区别 implements是实现接口的关键字
  2. 继承简例
class Animal {
   name : string;
   constructor( name: string){
      this.name = name
    }
    move(distance: number=0){
      console.log(`${this.name} mode ${distance}m`)
    }
}
class Snake extends Animal {
  constructor(name: string){
      super(name) //子类继承必须要写的 如果需要调用父类的时候
   }
   move(distance: number = 5){
      console.log('Slithering...')
      super.move(distance) 调用父类的方法
    }
}
let tom : Animal = new Snake('name  save')
tom.move() 调用父类方法
类 公共 私有 受保护的修饰符
  1. public 在上述例子中 每个父类的成员 name,constructor move 实际上都默认标记为public 标记为public就默认可以随意使用
  2. private 标记为private的时候 new的时候就访问不到了
  3. 子类new的结果与父类new的结果是互相兼容的
let animal = new Animal(name:'goad');
let rhino = new Rhino()
let employee = new Employee(name:'bonb')
animal= rhino //true
animal = employee ///false
上述的三个2是1的子类 同时2里面只有constructor里有个super 3跟1的结构一样 但是他们的来源是不一样的
  1. protected: 如果在父类中的constructor属性上加上protected 那么 这个类就不能被new 只能被extends 如果父类中的一个属性上被标示了protected这个属性 那么这个属性只能在extends子类中访问 在new里面不能被访问
  2. readonly:只读属性 在父类中对属性添加这个readonly的时候 在new中不能被修改
Ts存取器
  1. Ts存取器是通过getts和setts对对象成员的访问,存取器的实现实际也是使用了object.defineprototype这个属性例如
let passcode = ' secret1 passcode'
class Employee {
  private _fullName: string; //私有变量一般前面用下划线标示
  get fullName(): string { //调用私有变量的时候触发get方法
     return this._fullName
   }
   set fullName(newName: string){//修改的时候执行里面的逻辑
     if()。。。。else()...
   }
}
let employee = new Employee
employee.fullName = 'bob smith'
类的静态属性
//以下例子是利用勾股定理公式计算
calss Grid {
   static origin = {x:0;y:0}
   scale: number
   constructor(scale: number){
      this.scale = scale
   }
   calculateDIstanceFromOrigin(point: {x:number;y:number}){
      let xDist = point.x - Grid.origin.x //静态属性访问
      ......
    }
}
let grid1 = new Grid(scale:1.0)
console.log(grid1.calculateDIstanceFromOrigin(proint:{x:3;y:4}))
抽象类
  1. //抽象类通常是作为其他子类的基类使用,一般不能被直接实例话,里面抽象方法不能直接被实现,抽象类一般使用abstract关键字标明,里面的抽象方法也是使用此关键字,抽象方法一般只在继承抽象类的类中实现
abstract class Department {
    name: string

    constructor(name: string){
        this.name = name
    }
    printName(): void{
        console.log('Department name')
    }
    abstract printMeeting():void
}
class AccountingDepartment extends Department {
    constructor(){
        super('Accounting ad')
    }
    printMeeting():void{
        console.log('the account')
    }
    genterateReports(): void {
        console.log('Generating')
    }
}
// let department: Department
let department: AccountingDepartment
department = new AccountingDepartment()
department.printName()
department.printMeeting()
department.genterateReports()//报错 因为let department: Department department只中没有这个 
//如果想要不报错把let department: AccountingDepartment这样就行了
更改类的静态属性
class Greeter {
    static standardGreeting = 'Hello, there'

    greeting: string

    constructor(message?: string){
        this.greeting = message
    }

    greet() {
        if(this.greeting) {
            return 'Hello' + this.greeting
        } else {
            return Greeter.standardGreeting
        }
    }
}

let greeter: Greeter // greeter的类型是定义的类
greeter = new  Greeter()

let greeterMaker: typeof Greeter = Greeter//生成一个新的构造器来更改静态属性值
greeterMaker.standardGreeting = 'Hey there'

let greeter2: Greeter = new greeterMaker()
console.log(greeter.greet())
类当接口使用
class Point {
    x: number
    y: number
}
interface Point3d extends Point {
    z: number
}
let point3d: Point3d = {x:1,y:1,z:1}
函数重载
function pickCard(x: {suit:string; card:number}[]): number
function pickCard(x: number): {suit:string; card:number}
 //上述两个就是pickCard函数的重载 可以判断函数调用时传入的参数类型 第一个是传入数组 返回number
 //第二个重载是传入数字 返回对象
function pickCard(x): any{
    //里面写逻辑
    if(Array.isArray(x)){
        let pickedCard = Math.floor(x:Math.random() * x.length)
        return pickedCard
    }else if( typeof x === 'number'){
        let pickedSult = Math.floor(x: x/13)
        return {suit: suits[pickedSuit],card: x%13}
    }
}
泛型
/使用场景 例如想要有个函数 返回任何传入的值 使传入的类型与返回的类型相同 
//下面这种情况如果传入的是数字返回的是 字符串 不符合我们的需求
// function identity (arg: any): any{
//     return arg + ''
// }
//T是一个类型变量可以帮我们 捕获用户传入的类型 这样的函数我们就称为泛型
function identity <T>(arg: T): T{
    return arg
}
//使用 上述 泛型函数 例如
// let output = identity<string>('mystring')//标记T为string 传入的参数为string类型的 这样写有些亢长
//也可以直接写 泛型会自动解析
// let output = identity(arg:'mystring')

//使用泛型定义接口
// interface GenericIdentityFn {
//     <T>(arg: T): T
// }
// let myIdentity: GenericIdentityFn = identity

//定义泛型类的使用 静态类型不能使用泛型类
// class GenericNumber<T> {
//     zeroValue: T
//     add: (x: T, y: T) => T
// }

// let myGenericNumber = new GenericNumber<number>{
//     myGenericNumber.zeroValue = 0
//     myGenericNumber.add = function (x,y){
//         return x+ y
//     }
// }
泛型类+ 泛型约束
//泛型类 + 泛型约束
//例如 一个函数 里面有obj key 两个参数 返回obj[key]
//这时候对obj做类型约束为T k要存在于T得属性中 所以使用 K extends keyof T
function getProperty<T, K extends keyof T>(obj: T,key: K){
    return obj[key]
}
//调用上述函数 如果调用得key在x里面没有那么会报错
// let x = {a:1,b:2,c:3,d:4}
// getProperty(x, key:'a')

//使用泛型创建工厂函数

class BeeKeeper {
    hasMark: boolean
}
class LionKeeper {
    nametag: string
}
class Animal {
    numLengs: number
}
class Bee extends Animal{
    keeper: BeeKeeper
}
class Lion extends Animal{
    keeper: LionKeeper
}

//工厂函数
function createTnstance <T extends Animal>(c: new()=> T): T{
    return new c()
}
createTnstance(Lion).keeper.nametag//可以调用
createTnstance(Bee).keeper.hasMark//可以调用
交叉类型 可以合两个对象或实例
//交叉类型 例如把两个对象的类型组合到一起 下面我们来写这样一个函数
function extend<T,U>(first: T,second: U): T & U {
    let result = {} as T & U

    for(let id in first){
        result[id] = first[id] as any
    }
    for(let id in second){ //过滤掉result中已经有的id
        if(!result.hasOwnProperty(id)){
            result[id] = second[id] as any
        }
    }
    return result
}

class Person {
    constructor(public name: string) {

    }
}
interface Loggable {
    log(): void
}
class ConsoleLogger implements loggable{
    log() {
        // ...
    }
}
let jim = extend(new Person(name:'jim'),new ConsoleLogger())
//可以调用Person中的name和ConsoleLogger
jim.name
jim.log()
联合类型
  1. 联合类型和交叉类型的区别是 联合类型表示的是几种类型之一 如number | string,而交叉类型表示的是几种类型之和
  2. 如果定义了两个类型方法的接口 然后在一个函数上定义这两个类型接口的联合类型,这个函数只能返回两个类型接口的公共的函数类型,如果想要返回单独一个那就要确定好再返回,这个时候我们就可以用到类型保护了
类型保护
  1. 通过写一个函数判断是否为想要的类型 然后在使用联合类型的函数中调用这个判断的函数
function isNumber(x: any): x is number {
    return typeof x === 'number'
}
function isString(x: any): x is number {
    return typeof x === 'string'
}
function padLeft(value: string, padding: string | number){
    if(typeof padding !== 'number'){
        return Array(arrayLength:padding + 1).join('')+value
    }
    if(isString(padding)){
        return padding + value
    }
}```

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值