一、概述

1、什么是Typescript?

官方网站的定义是: TypeScript 是 JS 类型的超集TypeScript 是一个js的外壳,需要编译成浏览器可识别的javascript才可以运行。

2、为什么使用Typescript?

  • 弥补javascript缺少类型判断,缺少结构化机制(类、模块、接口等)的不足
  • 程序更容易理解 (‘代码即注释’)
  • 效率更高(编译期就会发现大部分错误)
  • 非常好的包容性(完全兼容js、流行项目都支持Ts)
    不足:增加了一些学习成本,短期内增加了一些成本,项目规模小,无必要使用

二、安装和初试

  • 安装
  1. npm install -g typescript
  • 编译
  1. tsc file.ts
  • 简便方法,安装ts-node
    每次都需要对ts文件编译产生js文件后再通过node 运行,比较麻烦
  1. npm i ts-node -g
  2. ts-node file.ts

三、数据类型

  • 原始数据类型

    • Boolean

      let isDone: boolean = false;

    • Null

      let null = null

    • Undefined

      let undefined = undefined

    • Symbol

    • String

      let firstName:string = “jimmy”

    • Number

      let age: number = 20 | 0b1111;

    • 注意: undefined和null是其他类型的子集

Eg:

let num: number = undefined | null

  • any类型,有明确类型避免使用

let notSure :any = 4 notSure = ‘1233’ notSure = true

  • 联合类型(|)

let numberOrString : number | string = 23

  • 数组类型

let arrOfNumbers:number[] = [1,2,3,4] arrOfNumbers.push(1) arrOfNumbers.push(‘1’) // error

  • Tuple—特殊定义数组类型的方式

let user:[string,number] = [‘hello’, 99] user = [“world”,”haha”] // error

  • interface

| 对对象的形状进行描述

| 对类进行抽象

| 鸭子类型 对象的推断,而不是对象本身

  1. interface IPerson{
  2. readonly idnumber;
  3. name:string;
  4. age?:number;
  5. }
  6. let tom: IPerson = {
  7. name : 'tom',
  8. id:1,
  9. age:19
  10. }
  11. // 注意: age后面的问号代表可选属性,代表该属性可以不存在,readonly代表只读属性,代表对象中的该属性只能读不能修改。注意接口命名首字母需要大写,I开头不强制, 每个属性定义后用";" 结尾
  • 函数类型
  1. // 对参数和返回值的约定
  2. const add = function(x:number,y:number,z?:number =10):number{
  3. if(typeof m === 'number'){
  4. return x + y + m
  5. }else{
  6. return x + y
  7. }
  8. }
  9. // let result = add(1,2)
  10. // let result = add(1,2,3)
  11. // z为可选类型可选类型放参数最后面
  12. // 类型推断,可以根据赋值推断变量类型
  13. const add2: string = add // error
  14. const add2:(x:number,y:number,z?:number =10)=>number = add // true
  15. eg
  16. let str = "hello"
  17. str = 123 // error
  18. str = "world" // true
  • class类的支持
  1. // 创建Animate类
  2. class Animate{
  3. public name:string; // 公有属性|默认属性
  4. readonly id:number; // 只读,不可修改赋值
  5. private size:number; // 私有方法,只有自己可以访问
  6. protected key:boolean;// 受保护的属性,自己和子类可以使用
  7. static categoies:string[] = ["mammal",brid]; // 静态属性
  8. static isAnimal(a){ // 静态方法
  9. return a instanceof Animate
  10. }
  11. constructor(name){
  12. this.name = name;
  13. }
  14. run(){
  15. return `${this.name} is running`
  16. }
  17. }
  18. // 继承父类
  19. class Cat extends Animate{
  20. constructor(name,key){
  21. super(name) // 继承父类的方法
  22. this.name = name;
  23. this.key = key;
  24. run(){ // 重写父类run方法
  25. return 'Meow, ' + super.run()
  26. }
  27. }
  28. }
  29. const cat = new Cat('miao',true)
  30. console.log(cat.run()) // 'Meow, miao is running'
  • 类和接口的使用—-implements
  1. // 提取公共的接口
  2. interface Radio{
  3. switchRadio(trriger:boolean) : void | number;
  4. }
  5. // Cellphone特有
  6. interface Battery{
  7. checkBattertStatus();
  8. }
  9. class Car implements Radio{
  10. switchRadio(){}
  11. }
  12. class Cellphone implements Radio,Battery{
  13. switchRadio(){}
  14. checkBattertStatus(){}
  15. }
  16. // 定义接口继承已有
  17. interface RadioWithBattery extends Radio{
  18. checkBattertStatus();
  19. }
  20. class Cellphone implements checkBattertStatus{
  21. switchRadio(){}
  22. checkBattertStatus(){}
  23. }
  • 枚举Enums

一般声明常量中使用,并且有一定关系

数字枚举

  1. enum Direction{
  2. Up,
  3. Down,
  4. Right,
  5. Left
  6. }
  7. console.log(Direction.Up) // 0
  8. console.log(Direction.Down) // 1
  9. console.log(Direction[0]) // Up
  10. 可以给Up赋值,后面的会递增

字符串枚举

  1. enum Direction{
  2. Up='UP',
  3. Down='DOWN',
  4. Right='RIGHT',
  5. Left='LEFT',
  6. }
  7. const value = 'UP'
  8. if(Direction['UP']===value){
  9. console.log('go up')
  10. }

常量枚举

只需要在枚举前面加const,会内联枚举,提高计算性能

  1. const enum Direction{
  2. Up='UP',
  3. Down='DOWN',
  4. Right='RIGHT',
  5. Left='LEFT',
  6. }
  • 泛型——generics
    泛型出现的动机和要解决的问题:
    在定义时没办法确定参数类型和返回类型的时候,在使用时才能确定
    可以简单理解为占位符,动态指定类型
  1. function echo(arg:number){
  2. return arg
  3. }
  4. const result = echo(123) // result is number
  5. const result = echo('123') // result is string change arg is string
  6. ...

result无法随意匹配any类型

改造后:

  1. function echo<T>(arg:T):T{ // 使用T作为参数占位
  2. return arg
  3. }
  4. const result:number = echo(123)
  5. const result:string = echo('123')
  6. const result:boolean = echo(true)

参数是一个数组的时候,加泛型

  1. function swap<T,U>(tuple:[T,U]):[U,T]{
  2. return [tuple[1],tuple[0]]
  3. }
  4. const result2 = swap(['string',123])
  5. result2[1] // number
  6. result2[0] // string

对函数使用泛型加约束

Eg:

  1. function echoWithArr<T>(arg:T):T{
  2. console.log(arg.length)
  3. return arg
  4. }
  5. // 会报错,因为T可能没有length,如果给T加约束
  6. function echoWithArr<T>(arg:T[]):T[]{
  7. console.log(arg.length)
  8. return arg
  9. }
  10. // 改造成了传T类型的数组,错误取消,但是如果想判断字符串的length呢,如果是对象中含有length呢,上面的改造就不能实现了,继续改造
  11. interface IWithLength{
  12. length:number;
  13. }
  14. function echoWithLength<T extends IWithLength>(arg:T):T{
  15. console.log(arg.length)
  16. return arg
  17. }
  18. const str = echoWithLength('str')
  19. const obj = echoWithLength({length:12,width:'12'})
  20. const arr = echoWithLength([1,2,3])
  21. // 以上都可以满足,问题解决

对类使用泛型约束

  1. class Queue<T>{
  2. private data = [];
  3. push(item:T){
  4. return this.data.push(item)
  5. }
  6. pop():T{
  7. return this.data.shift()
  8. }
  9. }
  10. const queue = new Queue<number>();
  11. queue.push(1)
  12. const queue2 = new Queue<string>();
  13. queue.push('1')

对接口加泛型

  1. interface KeyPair<T,U>{
  2. key:T;
  3. value:U;
  4. }
  5. let kp1:KeyPair<number,string> = {key:123,value="str"}
  6. let kp2:KeyPair<string,number> = {key:"str",value="123"}

对数组加泛型

  1. let arr:number[] = [1,2,3]
  2. let arr2:Array<number> = [1,2,3,4]
  1. interface IPlus<T> { // 描述了一个函数的类型
  2. {a:T,b:T}: T
  3. }
  4. function plus(a:number,b:number){
  5. return a+b;
  6. }
  7. function connect(a:string,b:string){
  8. return a+b;
  9. }
  10. const a:IPus<number> = plus;
  11. const b:IPus<string> = plus;
  • 类型别名和断言as
  1. // 别名 type aliases
  2. function sum(x;number,y:number):number {
  3. return x+y
  4. }
  5. const sum2:(x;number,y:number)=>number = sum
  6. // sum2 太长,用类型别名
  7. type PlusType = (x;number,y:number)=>number
  8. const sum2:PlusType = sum
  1. // 断言 as 分别判断不同类型的不同处理方式
  2. function sum(input:string | number) :number {
  3. const str = input as String;
  4. if(str.length){
  5. return str.length
  6. }else{
  7. const number = input as Number;
  8. return number.toString().length
  9. }
  10. }
  11. =>
  12. function sum(input:string | number) :number {
  13. if((<string>input).length){
  14. return (<string>input).length
  15. }else{
  16. return input.toString().length
  17. }
  18. }
  • 声明文件
  1. jQuery('#f00');

使用一

declare var jQuery:(selector:string)=>any

一般单独放在一个文件jQuery.t.ts 中声明,以.d.ts结尾

tsconfig.json

  1. {
  2. "include":["**/ *]
  3. }

使用二

第三方库

查找第三方库地址

npm install —save @types/jquery


studytypescript地址

四、Ts高级类型

1、交叉类型 &

使用 符号构造交叉类型

  1. type LeftType = {
  2. id: number
  3. left: string
  4. }
  5. type RightType = {
  6. id: number
  7. right: string
  8. }
  9. type IntersectionType = LeftType & RightType
  10. function showType(args: IntersectionType) {
  11. console.log(args)
  12. }
  13. showType({
  14. id: 1, left: "test", right: "test"
  15. })

2、联合类型 |

使用 | 符号构造交叉类型

  1. type UnionType = string | number
  2. function showType(arg: UnionType) {
  3. console.log(arg)
  4. }
  5. showType("test")
  6. // Output: test
  7. showType(7)
  8. // Output: 7

3、泛型

泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。

  1. interface GenericType<T, U> {
  2. id: T
  3. name: U
  4. }
  5. function showType(args: GenericType<number, string>) {
  6. console.log(args)
  7. }
  8. showType({ id: 1, name: "test" })
  9. // Output: {id: 1, name: "test"}
  10. function showTypeTwo(args: GenericType<string, string[]>) {
  11. console.log(args)
  12. }
  13. showTypeTwo({ id: "001", name: ["This", "is", "a", "Test"] })
  14. // Output: {id: "001", name: Array["This", "is", "a", "Test"]}

4、内置类型

  • Partial 类型 (将T类型的所有必选属性设为可选属性)

    1. interface PartialType{
    2. id:number,
    3. name:string
    4. }
    5. function showType(args:Partial<PartialType>){
    6. console.log(args)
    7. }
    8. showType({1})
  • Required 类型 (将T类型的所有可选属性设为必选属性)

    1. interface PartialType{
    2. id:number,
    3. name?:string
    4. }
    5. function showType(args:Required<PartialType>){
    6. console.log(args)
    7. }
    8. showType({1,'xiaohua'})
  • Readonly 类型 (将T类型的所有属性设置为只读,如果赋值保错)

    1. interface ReadonlyType{
    2. id:number,
    3. name:string
    4. }
    5. function showType(args:Readonly<ReadonlyType>){
    6. args.id = 5 // Error: Cannot assign to 'id' because it is a read-only property.
    7. }
    8. showType({1,'xiaohua'})
  • Pick类型 从T中取出K中选择出指定的属性

    1. interface PickType{
    2. id:number,
    3. name:string,
    4. firstName:string
    5. }
    6. function showType(args:Pick<PickType,"name"|"firstName">){
    7. console.log(args)
    8. }
    9. showType({ name: "John", firstName: "Doe" }) //=> John
    10. showType({ id: 3 }) //=> Error: Object literal may only specify known properties...
  • Omit类型 与Pick相反, 从T中选取K属性进行删除 ```javascript interface PickType { id: number firstName: string lastName: string }

function showType(args: Omit) { console.log(args) }

showType({ id: 7 }) // Output: {id: 7}

showType({ firstName: “John” }) // Error: Object literal may only specify known properties,

  1. <a name="Hae1O"></a>
  2. #### 5、Extract
  3. - `Extract`<br />
  4. `Extract` 从 `T` 中提取所有可分配给 `U` 的类型。 有多个共同字段,`Extract` 将提取所有共同的属性
  5. ```json
  6. interface FirstType {
  7. id: number
  8. firstName: string
  9. lastName: string
  10. }
  11. interface SecondType {
  12. id: number
  13. address: string
  14. city: string
  15. }
  16. type ExtractType = Extract<keyof FirstType, keyof SecondType>
  17. // Output: "id"
  • Exclude 从T中排除分配给U的类型 ```json interface FirstType { id: number firstName: string lastName: string }

interface SecondType { id: number address: string city: string }

type ExcludeType = Exclude

// Output; “firstName” | “lastName” ```

五、 参考

TypeScript高级类型