TypeScript学习笔记

117 阅读4分钟

一、类型定义

1.1 基本类型定义

let count : number = 1;

1.2 对象类型定义

// 方法一
type objType = { name: string, age: number }
const obj = <objType>{
 name: "chang",
 age: 18
}
// 方法二
const obj : {
   name : string ,
   age : number
} = {
   name : 'chang',
   age : 20
}
console.log(obj);

1.3 数组类型定义

// 定义一个字符串数组
const str_arr: string[] = ['str1', 'str2']
console.log(str_arr);

// 定义一个string,number都具有的数组
const str_num_arr: (string | number)[] = ['str1', 11, 'str2', 20]
console.log(str_num_arr);

// 对象类型的数组
type objType =  { name: string, age: number }
const obj_arr:objType[] = [
  { name: 'zs', age: 20 },
  { name: 'ls', age: 22 },
]
for (let item of obj_arr) {
  console.log(item);
}

1.4 元组类型的定义

// 元组数据类型定义
const person: [number, string] = [20, 'chang']
console.log(person);

1.5 类类型定义

class Person {
  name: string
}
const p1: Person = new Person()
p1.name = 'chang'
console.log(p1);

1.6 函数类型 定义

// 创建一个参数为 字符串类型,返回值为字符串类型的函数
type fnType = (param: string) => string
const func: fnType = (param) => {
  console.log(param);
  return 'success'
}
const fun1 = func('hello')
console.log(fun1);

1.6.1 有关函数返回值

// 函数参数为简单数据类型时
// 创建一个加法函数,返回两个数字类型数据的和
function add(num1: number, num2: number): number {
  return num1 + num2
}
console.log(add(1, 2));

// 函数参数为对象时
function add({ one, two }: { one: number, two: number }) {
  return one + two
}
const total = add({ one: 1, two: 2 })
console.log(total);     //3 

1.7 联合类型和类型断言

interface Waiter {
  anjiao: boolean;
  say: () => {}
}

interface Teacher {
  anjiao: boolean;
  skill: () => {}
}

function judge(person: Waiter | Teacher) {
  // person:Waiter | Teacher 这就是联合类型
  // // 方法一
  // if (person.anjiao) {
  //   (person as Teacher).skill()   // as 类型断言, 如果一个人会按脚那么就作为技师,调用技师的方法。
  // } else {
  //   (person as Waiter).say()
  // }

  // 方法二
  if ('skill' in person) {      // 使用in 判断一个方法是否在一个实例上
    person.skill()
  } else {
    person.say()
  }


  // 方法三 
  // 使用typeof 进行类型的判断
}


// 类型保护 方法四 instanceOf
class NumObj {
  'count': number
}

function addObj(first: object | NumObj, second: object | NumObj) {
  if (first instanceof NumObj && second instanceof NumObj) {
    // 当两个参数都属于指定对象类型的时候
    return first.count + second.count
  }
  return 0
}

1.8 枚举类型

enum Status {   // 定义一个枚举类型
  ANMO,
  SPA,
  DBJ
}   // 默认情况下枚举类型的索引是从0开始的
function getServe(status: any) {
  if (status === Status.ANMO) {
    return 'anmo'
  } else if (status === Status.SPA) {
    return 'spa'
  } else if (status === Status.DBJ) {
    return 'dbj'
  }
}
console.log(Status);   //  { '0': 'ANMO', '1': 'SPA', '2': 'DBJ', ANMO: 0, SPA: 1, DBJ: 2 }
const res = getServe(0)
console.log(res);    // anmo

1.8.1 默认索引

一般情况下,枚举类型的索引默认是从0开始的,如果想改变这种索引可以:


enum Status {   // 定义一个枚举类型
  ANMO = 1,
  SPA,
  DBJ
}
console.log(Status);   // { '1': 'ANMO', '2': 'SPA', '3': 'DBJ', ANMO: 1, SPA: 2, DBJ: 3 }

二、接口

2.1 基本接口定义与使用

interface Person {
  name: string;    // 字符串类型的name属性
  age?: number;    // 可选属性age
  readonly sex: string;   // 只读属性 sex
  [propname: string]: any;
  // 任意多个字符串类型的属性,值为any
  say():void;      // 一个空类型的函数
}
const arr: Person[] = [
  { name: 'chang', age: 20, sex: 'boy', height: 170 },
  { name: 'zs', age: 20, sex: 'gril', height: 180 }
]

// 接口应用
const p1: Person = {
  name: '小红',
  age: 18,
  sex: 'boy',
  height: 180,
  say() {
    console.log('hello');
  }
}
p1.say()

附加: readonly 和const 的区别

readonly:作为属性使用。 const :作为变量使用。

//  const 
const obj = {
  name: 'zs'
}
obj.name = 'lx'     // 对于obj的属性可以进行更改
obj = {}            // 这里会报错, 对于obj本身变量 不能进行修改

2.2 接口的继承

interface Person {
  name: string;    // 字符串类型的name属性
  age?: number;    // 可选属性age
  readonly sex: string;   // 只读属性 sex
  [propname: string]: any;
  // 任意多个字符串类型的属性,值为any
  say(): void;

}

interface girl extends Person {
  hairColod: string
}

三、class类

3.1 类的基本使用(定义继承)

class Animal {
  name: string
  constructor(theName: string) {    // 构造函数 得到一个字符串格式的名字参数
    this.name = theName
  }
  move(distance: number): string {
    return `${this.name} move ${distance} meter.`
  }
}

class Horse extends Animal {
  // 子类对于父类的继承
  constructor(theName: string) {
    super(theName)
  }
  // 子类对于父类的重写
  move(distance: number): string {
    console.log('Horse');
    return super.move(distance)
  }
}

const h1 = new Horse('的卢')
const res = h1.move(56)
console.log(res);       //  Horse\n的卢 move 46 meter.

3.2 类的属性修饰符

public private protected readonly

public :默认情况下为public。

private :不能在声明它的类的外部访问。

protected:可以在声明它的类和它的子类中访问。

readonly: 只读属性

class Animal {
  protected name: string;       // 当为private的时候,子类不能访问到父类的私有属性
  constructor(theName: string) { this.name = theName; }
  getName() {
    return `${this.name}`
  }
}
class Rhino extends Animal {
  constructor() {
    super("Rhino");
    console.log(this.name);    //  当为protected的时候可以访问到
  }
}
let animal = new Rhino();

3.2 类的Getter、Setter和static

class Animal {
    private name: string;
    constructor(theName: string) { this.name = theName; }
    get Pname() {
      return this.name
    }
    set Pname(name:string){
        this.name = name
    }
}
const a1 = new Animal('monkey')
console.log(a1.Pname);    // monkey
a1.Pname = 'donkey'
console.log(a1.Pname);    // donkey

3.3 静态属性static

无需实例化就可以调用类里面的静态方法

class Girl{
    static sayLove(){
        console.log('I love you');
    }
}
Girl.sayLove()   // I love you

3.4 抽象类 abstract

// 抽象类的定义,被继承者必须带有该抽象类的抽象方法
abstract class Girl {
    abstract skill()
}

class Waiter extends Girl{
    skill(){
        console.log('服务员,端茶倒水');
        
    }
}
class BaseTeacher extends Girl{
    skill(){
        console.log('基础技师,泰式按摩');
    }
}
class SeniorTeacher extends Girl{
    skill(){
        console.log('高级技师,SPA全身按摩');
    }
}

4. tsconfig.json

1. ts的配置文件

安装完typescript之后,在文件夹中使用tsc -init出现tsconfig.json配置文件。

2. 基本的配置说明

"include":[],                                /* 需要编译的文件数组 */
"exclude":[],                                /* 不编译的文件数组 */
"file":[],                                   /* 与include作用一样  */
"outFile":'./',                              /* 将多个文件编译成单个文件,不在支持common.js-> AMD  */
"removeComments": true,                      /* 去掉注释  */
"strict": true,                              /* 是否使用严格模式 */
"noImplicitAny": true,                       /* 允许any类型的数据格式不用特意声明 */
"strictNullChecks": true,                    /* 不允许Null值出现  */ 
"outDir": "./",                              /* 出口文件夹 */
"rootDir": "./",                             /* 入口文件夹  */
"sourceMap": true,                           /* ts文件和js文件的映射 */
"noUnusedLocals": true,                      /* 无用的变量编译前会提示  */
"noUnusedParameters": true,                  /* 无用的方法编译前会提示  */

5 泛型

个人理解: 动态格式的规定

5.1 基本的泛型使用

function join<T>(first: T, second: T) {
  return `${first}-${second}`
}
// 基本的泛型,规定函数的两个参数的类型必须一致
const res = join<string>('hello', 'world')
console.log(res);

5.2 泛型中使用数组

// 泛型中数组的使用
function getArr<T>(param: T[]) {   
// function getArr<T>(param: Array<T>){ 
  return param
}
const res = getArr<string>(['123', '456'])

5.2 多个泛型的定义

function join<T, P>(first: T, second: P) {
  return `${first}-${second}`
}
// 基本的泛型,规定函数的两个参数的类型必须一致
const res = join<string, number>('hello', 1)
// 泛型的类型推断 
// const res = join('hello', 1)   //直接写也是可以的,但是不推荐
console.log(res);

5.3 泛型在类中的基本使用

class XJJ<T>{
    constructor(private girls:T[]){}
    getGirl(index:number):T{
        return this.girls[index]
    }
}
const setGirls = new XJJ<string>(['王冰冰','范冰冰','高圆圆'])
console.log(setGirls.getGirl(1));

5.4 泛型约束

interface Girl{
    name : string
}
class XJJ<T extends Girl>{
    constructor(private girls:T[]){}
    getGirl(index:number):string{
        // 返回值为name,name的类型为string,返回值为string
        return this.girls[index].name
    }
}
const setGirls = new XJJ([
    {name:'王冰冰'},
    {name:'范冰冰'},
    {name:'高圆圆'}
])
console.log(setGirls.getGirl(1));   // 范冰冰

6. 命名空间的使用

6.1 基本使用

命名空间这个语法,很类似编程中常说的模块化思想,每个模块有自己的环境,不会污染其他模块,不会有全局变量产生。

命名空间声明的关键词是namespace 比如声明一个namespace Home,需要暴露出去的类,可以使用export关键词,这样只有暴漏出去的类是全局的,其他的不会再生成全局污染了。

namespace Home {
  class Header {
    constructor() {
      const elem = document.createElement("div");
      elem.innerText = "This is Header";
      document.body.appendChild(elem);
    }
  }

  class Content {
    constructor() {
      const elem = document.createElement("div");
      elem.innerText = "This is Content";
      document.body.appendChild(elem);
    }
  }

  class Footer {
    constructor() {
      const elem = document.createElement("div");
      elem.innerText = "This is Footer";
      document.body.appendChild(elem);
    }
  }

  export class Page {
    constructor() {
      new Header();
      new Content();
      new Footer();
    }
  }
}
<!DOCTYPE html>
<html lang="en">
<body>
  <script>
    new Home.Page()
  </script>
</body>
</html>

image.png

6.2 子命名空间


namespace Components {
  export namespace SubComponents {
    export class Test {}
  }
}
// 使用
Components.SubComponents.Test