Typescript入门学习

1. 编程语言的类型 : 动态类型语言 和 静态类型语言(c\ C++ \Jave)

2. Typescript 是什么 ?

  1.  是通过在JavaScrip的基础上添加了静态类型风格的类型系统
  2.  对es6到es10的预发支持,兼容各种浏览器

3. 为什么要使用Typescript

优点:

  • 程序容易理解 定义函数或者方法输入输出的参数类型可容易理解程序
  • 效率更高 ,通过ide代码可自动补全、自动识别错误信息
  • 包容性好 , 完全兼容JavaScript
    缺点:
  • 学习成本高
  • 短期增加了一些开发成本

4. 安装typescript

 node版本12.5.0 ,建议 10以上,  npm 版本6.9.0  ,tsc 版本3.8.3
 ts-node XXX.ts  执行ts,输出结果
 tsc  XXX.ts    编译ts为js文件

5. Typescript数据类型

原始数据类型 string、boolean、number、undefined 、null

      注意 undefined 和 null 是所有类型的子类型,可以随意赋值给其它数据类型。
      let  flag :boolean = true
      let   issure: any = 123    // 不确定数据类型用法
      issure = "abc"

复杂数据类型 数组array 和元组 tuple

        let arr1: number[] = [12, 2, 34]
        let arr2: [number, string] = [123, 'abc']

interface接口 针对object进行约束

        interface IPerson {
              readonly id : number;    //readonly  只读不可编辑
              age ? : number,             // ?     IPerson   age属性可有可无
              name : string
          }
        let na : IPerson = {
              id:1,
              age : 2 , 
              name: 'nana'
        }

interface接口 针对数组对象进行约束

class Data {
    [propName: string]: any
}
interface Ret {
    code: number,
    data: Array<Data>,
    message: String
}

const ret: Ret = {
    code: 200,
    data: [{ id: 1 }],
    message: '错误信息'
}

console.log(ret.data[0].name)

interface接口 针对function输入输出约束

    interface ISum {
      (x:number,y:number,z ?: number) :number
    }
    let add :ISum = (x:number,y:number,z ?:number):number => {
          if( typeof z === 'number'){
                    return x + y + z
          }else{
                   return x + y
          }    
    }
    add(1,2,3)

6. 类型推断 联合类型 类型断言

let  num =  123;    //  num 此时类型被推断为 number类型,不可修改为其他类型

//联合类型 union types : 不确定一个类型的变量到底是哪个类型的时候 ,只需要用中竖线来分割两个类型,此时只能访问此联合类型的所有类型里共有的属性或方法:
let numberOrstring: number | string;
numberOrstring = 123;
numberOrstring = 'abc';


//类型断言  可以用 as 关键字,告诉typescript 编译器参数。
function getLength(input : number | string) :number {
  const inp = input as string;
  if(inp.length){
      return inp.length
  }else{
      const num = input as  number;
      return num.toString().length
  }
}

7. Class 类

在JavaScript 使用构造函数 原型链实现继承;
Es6出现Class概念,内部使用原型链机制实现 ,有了面向对象的概念;
面向对象基本术语:

  • 类(class) :定义了一切事物的抽象特点
  • 对象 (Object) : 类的实例,通过New生成
  • 面向对象 (OOP) 三大特性:封装 、继承、多态
    封装: 将数据操作细节隐藏起来,对外只暴露接口,只通过接口访问该对象。 创建一个Animal类
class Animal {
  constructor(name){
      this.name = name;
  }
  run(){
    return `${this.name} is running`
  }
}
const snake = new Animal('snake')
console.log(snake.run())

继承: 子类可以继承父类的特征 。通过extends继承

class Dog extends Animal{
    eat(){
        return `${this.name} is eatting`
     }
}
const kele = new Dog('kele')
console.log(kele.run())
console.log(kele.eat())

多态: 通过继承,子类也可以拥有自己的方法。

class Cat extends Animal{
  static cate = ['cateqqq']   //静态属性、方法,与实例没有太大的关系
  construcor(name){
    super(name)   //重写构造函数需要使用super方法
  }
  run(){
    return 'Hi,' + super.run()   //调用父类方法需要使用 super关键字
  } 
}
const maomao = new Cat('maomao')
console.log(maomao.run())
console.log(Cat.cate )

Typescript中的class
3种访问修饰符 ,类上的属性和方法添加权限管理

  • Public :修饰的属性和方法是共有的,可以在任何地方被调用到,默认使用的
class Animal {
    name: string;
    constructor(name) {
        this.name = name;
    }
    run() {
        return `${this.name} is running`
    }
}
const snake = new Animal('snake')
console.log(snake.run())
  • private : 修饰的属性和方法是私有的,子类也不可以访问和修改
class Animal {
    name: string;
    constructor(name) {
        this.name = name;
    }
   private  run() {
        return `${this.name} is running`
    }
}
const snake = new Animal('snake')   
console.log(snake.run())  //报错  属性'run'为私有属性,只能在类'Animal '中访问
  • Protected: 修饰的属性和方法是受保护的,子类可以访问
  • readonly : 只能读 不可以写
class Animal {
    readonly   name: string;
    constructor(name) {
        this.name = name;
    }
    protected run() {
        return `${this.name} is running`
    }
}
class Cat extends Animal {
    construcor(name) {
        super(name)   //重写构造函数需要使用super方法
    }
    run() {
        return 'Hi,' + super.run()   //调用父类方法需要使用 super关键字
    }
}
const maomao = new Cat('maomao')
console.log(maomao.run())

8. 类和接口 搭档使用

interface 用于对对象的形状进行描述,描述函数的类型,对类的一部分形为进行抽象。

  • 继承困境 : 一个类只能继承自另外一个类,不同类之间需要有共同的特性,使用子类调用父类的方法不太合适。
  • 特性提取成接口,用一个 implements关键字来实现接口,提高面向对象的灵活性。
//特性1 :收音机
interface Radio {
    switchRadio(trigger: boolean): void     //void关键字代表什么也不返回
}
//特性2 :检查电池容量
interface Checkbox {
    checkBoxStatus(): void
}
//特性3 : 接口之间的继承   RadioWithCheckbox 接口继承Radio  ,即有开关收音机又有检查电池容量
interface RadioWithCheckbox extends Radio {
    checkBoxStatus(): void
}
class Car implements Radio {
    switchRadio(trigger: boolean) {
    }
}
//可写为 class Mobile implements Radio ,Checkbox   ,也可以写为 :
class Mobile implements RadioWithCheckbox {
    switchRadio(trigger: boolean) {
    }
    checkBoxStatus() {
    }
}

9. 枚举 enums

枚举: 指的是常量情况,执行程序不会改变 ,在js中用const , 取值在一定范围内的一系列常量,例 一周7天; 这种情况需要用枚举表示

//数字枚举
enum Direction {
    Up,   //0       Up也可手动赋值 10, 下面会自动递增  Up = 10
    Down, //1
    Left, //2
    Right //3
}

console.log(Direction.Up)   //返回0
console.log(Direction[0])   //返回Up

//字符串枚举 ,提升性能  编译代码简单
enum DirectionS {
    Up = 'UP',
    Down = 'DOWN',
    Left = 'LEFT',
    Right = 'RIGHT'
}
const value = 'UP'
if (value === DirectionS.Up) {
    console.log('go up!')
}

10. 泛型 Generics

泛型 指定义函数 接口或 类的时候不予先指定具体类型,而是在使用的时候在指定类型的一种特征

//泛型定义进阶1
function echo(arg) {
    return arg
}
const result = echo(123)   //发现返回结果为any类型,变量丧失了类型
//泛型定义进阶2
function echo1(arg: number): number {
    return arg
}
const result1 = echo1(123)    // echo1返回number类型,但需求有可能传入各种类型,满足不了需求
//泛型定义进阶3
function echo2(arg: any): any {
    return arg
}
const result2: string = echo2(123)    //丧失类型,返回any类型,还存在一个问题,传入和返回的值无法做到统一,返回any类型,传入的string类型 属于any下的类型 

//泛型使用generics 占位符传入1个参数
function echo3<T>(arg: T): T {
    return arg
}      
const result3 = echo3(123)  //传入数字123,通过类型推断,返回数字类型

//泛型使用generics 占位符传入元组
function swap<T, U>(tuple: [T, U]): [T, U] {
    return (tuple[0], tuple[1])
}
const result4 = swap(['string', 123])

约束泛型

// 泛型约束进阶1
function echoWithArr<T>(arg: T): T {
    console.log(arg.length)  //报错,类型T上不存在length属性,所以得对泛型做约束
    return arg;
}

//泛型约束进阶2 
function echoWithArr1<T>(arg: T[]): T[] {
    console.log(arg.length)
    return arg;
}
const arrs = echoWithArr1([1, 2, 3])   //返回正确的number数组,处理并不完美, string和对象都可能有length属性
// const str = echoWithArr1('str')      //返回报错,string类型参数不能赋值给元组[]类型


//进行约束,只允许这个函数传入包含length属性的变量,新建一个interface ,包含length属性  

interface Iwithlength {
    length: number
}
//使用extends关键字约束传入的泛型,只返回传入的参数有length属性
function echoWithLength<T extends Iwithlength>(arg: T): T {
    console.log(arg.length)
    return arg
}
const str1 = echoWithLength('str')
const obj1 = echoWithLength({ length: 10 })
const arrs2 = echoWithLength([1, 2, 3, 4])
const num = echoWithLength(10)   //错误,类型number的参数不能赋值给Iwithlength的参数

类泛型约束

// 类泛型进阶1
class Queue {
    private data = [];
    push(item) {
        return this.data.push(item)
    }
    pop() {
        return this.data.shift()
    }
}
const queue = new Queue()
queue.push(1)
queue.push('str')
console.log(queue.pop().toFixed())   //删除第一个元素并返回1  ,数字1可以使用toFixed方法
console.log(queue.pop().toFixed())   //ts不报错,但是编译js后会报错,  string类型不可以使用toFixed方法

//类泛型约束  解决上诉问题 ,无论什么类型被推入队列 , 推出的类型和推入类型一致
class Queue1<T>{
    private data = [];
    push(item: T) {
        return this.data.push(item)
    }
    pop(): T {
        return this.data.shift()
    }
}
const queue1 = new Queue1<number>()
queue1.push(1)
queue1.push('sre')    //报错类型string的参数不能赋值给类型number的参数
console.log(queue1.pop().toFixed())

泛型在interface的应用

interface Keypair<T, U> {
    key: T
    value: U
}  //key,value 的值动态传入
let kp1: Keypair<number, string> = { key: 1, value: 'str' }
let kp2: Keypair<string, number> = { key: 'str', value: 1 }
let kp3: Keypair<string, number> = { key: 1, value: 2 }  //报错 不能将key的类型number传入 string类型

泛型表示number数组类型

let arr1: number[] = [12, 2, 34]
let arr2: Array<number> = [1, 2, 3]

11.类型别名、字面量 、交叉类型

  • 类型别名type-aliase
let sum: (x: number, y: number) => number
const result = sum(1, 2)

//每次写入繁杂,可使用type关键字创建类型别名
type PlusType = (x: number, y: number) => number
let sum2: PlusType
const result2 = sum2(2, 3)
//也可使用type创建联合类型
type StrOrNum = string | number
let result3: StrOrNum = 'abc'
result3 = 124
  • 字符串 字面量 ,可以提供非常方便的一系列常量写法
const str: 'name' = 'name'
const number: 2 = 2
type Directions = 'Up' | 'Down' | 'Left' | 'Right'
let toWhere: Directions = 'Left'
  • 交叉类型
interface IName {
    name: string
}
type IPerson = IName & { age: number }
let person: IPerson = { name: 'a', age: 27 }

12.声明文件

使用第三方库的时候,第三方库不是通过typescript写的 ,直接使用jQuery('#foo')报错,需要通过declare var 声明

declare var jQuery: (selector:string) = > any ;   
//声明语句,仅仅全局定义jquery的类型,编译时的检查,最简单的声明文件写法
 jquery.d.ts    //声明语句放到声明文件中

使用第三库的typescript社区 :,可直接安装它的类型文件 
[社区地址] (https://www.typescriptlang.org/dt/search?search=)

13.内置类型

在ts中可以随意使用最新的JavaScript语法

  • 默认内置类型
//global objects
const arr: Array<number> = [12, 23, 3]
const date = new Date()
date.getTime()
const reg = /abc/
reg.test('as')
Math.pow(1, 2)
//Dom and Bom
let body = document.body;
let allLis = document.querySelectorAll('li')
allLis.length
document.addEventListener('click', (e) => {
    e.preventDefault()
})
//Partial   把传入的类型可变成可选
interface Iperson {
    name: string
    age: number
}
let viking: Iperson = { name: 'na', age: 12 }
type Ipartial = Partial<Iperson>   // Iperson的参数都变为可选参数
let viking2: Ipartial = {}

// Omit 可以忽略传入的某个属性
type Iomit = Omit<Iperson, 'name'>   //忽略name属性
let viking3: Ipartial = { age: 12 }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容