【专项学习】—— TypeScript基础语法入门

一、TypeScript定义

①typescript是javascript的超级,同时它拥有静态的类型;
②typescript会被编译成普通的javascript代码,然后再去运行。

//js中为动态类型
let a = 123;
a = '123';

//ts为静态类型
let b: number = 123; //(未来存储的类型 只能是数字类型)
b = '123'; //报错
b = 456; //不报错

二、TypeScript带来了什么优势?

①开发过程中,发现潜在问题
②更友好的编辑器自动提示
③代码语义更清晰易懂

function demo(data){
   return Math.sqrt(data.x ** 2 + data.y ** 2);
}

demo(); //js中线上运行才会发现错误

function tsDemo(data: { x: number, y: number}) {
   return Math.sqrt(data.x ** 2 + data.y ** 2);
}

tsDemo(); //vsCode编辑器会提示报错
tsDemo({x: 1, y:123}); //正确写法

// typescript类型自定义类型(别名语法) —— 使可读性更好
// type Point = { x: number, y: number }
interface Point { x: number, y:number }

function tsDemo(data: Point){
   return Math.sqrt(data.x ** 2 + data.y ** 2);
}

tsDemo({ x: 1, y: 123 });

三、静态类型的深度理解

interface Point {
      x: number,
      y: number
} 

//point变量上具备Point类型所有的属性和方法
const point: Point = {
      x: 3,
      y: 4
}

四.基础类型和对象类型  

/基础类型 
//number、string、boolean、null、undefined、symbol、void(空)
const count : number = 123;
const teacherName : string = 'Dell';

//对象类型
//对象、数组、函数
const teacher: {
   name: string,
   age: number
} = {
   name:  'Dell',
   age: 18
};

//数组的每一项是数字
const numbers: number[] = [1, 2, 3];

class Person {}

//dell必须是Person类对应的对象
const dell:Person = new Person();

//getTotal是一个函数,返回值是一个number
const getTotal: () => number = () => {
   return 123;
}

五.类型注解和类型推断  

// type annotation 类型注解  我们来告诉TS变量是什么类型

let count: number;
count = 123;

// type inference  类型推断  TS会自动的去尝试分析变量的类型

let countInference = 123;

// 如果 TS 能够自动分析变量类型,我们就什么也不需要做了
// 如果 TS 无法分析变量类型的话,我们就需要使用类型注解

const firstNumber = 1;
const secondNumber = 2;
const total = firstNumber + secondNumber;  //可以类型推断出number类型

//函数参数需要 类型注解 具体的类型
function getTotal(firstNumber: number, secondNumber: number){
   return firstNumber + secondNumber
}

const total = getTotal(1, 2); //可以类型推断出number类型

六.函数相关类型  

//函数返回值类型约束为 number 类型
function add(first: number, second: number) : number {
   return first + second
}

const total = add(1, 2);

//函数返回值为 void 类型 —— 空,函数没有返回值
function sayHello(): void{
   console.log('hello');
}

//函数返回值为never类型 —— 函数永远不会执行到最后
function errirEmitter(): never{
  throw new Error();
  console.log(123);   //不会执行
}    

//函数参数是对象解构 —— 只要是解构,类型注解必须在{}里
function add(
    {first, second}: {first: number, second: number}
): number{
  return first + second;
}
const total = add({ first: 1, second: 2 });

function getNumber({ first } : { first : number }) {
  return first;
}
const count = getNumber({ first: 1 });

七、数组和元组  

//数组
const arr: (number | string )[] = [1, '2', 3];
const stringArr: string[] = ['a', 'b', 'c'];
const undefinedArr: undefined[] = [undefined];

//类型别名 type alias
type User = {name: string, age: number};

const objectArr: User[] = [{
   name: 'dell',
   age: 28
}]

class Teacher {
   name: string;
   age: number;
}

const objectArr: Teacher[] = [
  new Teacher();
  {
      name: 'dell',
      age: 28
  }
];

//元组 tuple
//数组的长度是固定的,数组中每一项的类型也是固定的
const teacherInfo: [string, string, number] = ['Dell', 'male', 18];
//csv
const teacherList: [string, string, number][] = [
    ['dell', 'male', 19],
    ['sun', 'female', 26],
    ['jeny', 'female', 38]
]

  

八、Interface接口 

Interface是开发中,帮助我们进行语法提示、语法校验的工具,真正编译为js时会被剔除

//interface定义通用类型 —— 只能代表函数或对象,不能代表基础类型
interface Person {
  name: string;
  age?: number;                  //?表示age属性可有可无
  //readonly sex: string;       //readonly表示属性只能读 不能写入
  [propName: string]: any;   //person里多一个属性 不会报错
  say(): string;
}

//Teacher类型 继承自 Person类型
interface Teacher extends Person {
   teach(): string
}

//interface定义函数的类型声明
interface SayHi {
     //参数是string类型,返回值是string类型
     (word: string): string
}

//interface 和 type相类似,但并不完全一致
//type定义类型别名 —— 可以定义基础类型
type Person1 = string;

const getPersonName = (person: Person): void => {
  console.log(person.name);
};
 
const setPersonName = (person: Teacher, name: string): void => {
  person.name = name;
}

const person = {
  name: 'dell',
  sex: 'male',
  say() {
       return 'say hello';
  },
  teach() {
       return 'teach';
  }
}

getPersonName(person);   //person缓存变量直接传入,不严格,多一个属性不报错
getPersonName({
   name: 'dell',
   sex: 'male' ,   //对象字面量直接传入,严格,多一个属性会报错
   say() {
       return 'say hello';
   }
})

setPersonName(person, 'lee');

//类User 应用 接口Person —— 要求类里 必须有接口的属性和方法
class User implements Person {
    name = 'dell';
    say() {
         return 'hello'
    }
}

const say : SayHi = (word: string) => {
    return word;
}

九.类的定义和继承  

class Person {
       name = 'dell';
       getName() {
             return this.name;
       }
}

class Teacher extends Person {
       getTeacherName(){
             return 'Teacher'
        }
       getName() {
            //当类覆盖父类的方法之后,使用super调用父类的getName方法
            return  super.getName() + 'lee';   
       }
}

const person = new Person();
console.log(person.getName());

const teacher = new Teacher();
console.log(teacher.getTeacherName());

  

十.类中的访问类型和构造器 

①public 允许我在类的内外被调用
②private 允许在类内被使用
③protected 允许在类内及继承的子类中使用

//什么都不写,默认隐藏了public
class Person {
      protected name: string;
      public sayHi() {
            this.name;   
            console.log('hi');
      }
}

class Teacher extends Person {
      public sayBye() {
            this.name;
      }
}

const person = new Person();
person.name = 'dell';
console.log(person.name);
person.sayHi();


//constructor 构造器
class Person {
   //传统写法
   //public name: string;
   //constructor(name: string) {    //在new一个实例的瞬间被执行
   //     this.name = name;
   // }

   //简化写法 —— 初始化赋值
   constructor(public name: string) {}
}

//如果父类、子类都有构造器,子类要手动调用一下父类的构造器,否则报错
class Teacher extends Person {
   constructor(age: number) {
         super('dell')  //调用父类的构造函数时,要按父类的要求,传入参数
                            //如果父类是一个空类,没有构造器,也要调用super
   } 
}

const person = new Person('dell')
console.log(person.name);     

const teacher = new Teacher(28);

十一.静态属性,类里的Setter和Getter  

①Getter get可用于加密,确保变量的安全性
②Setter set也可以帮助保护私有变量

class Person {
      constructor(private _name: string){ }
      get name() {
            return this._name + 'lee'
      }
      set name(name: string){
            const realName = name.split(' ')[0];
            this._name = realName;
      }
}

const person = new Person('dell');
console.log(person.name);
person.name = 'dell lee';
console.log(person.name);

设计模式单例模式:一个类只允许通过这个类获取一个这个类的实例  

class Demo {
      private static instance: Demo;
      //不允许外部直接通过new创建实例
      private constructor(public name: string) {}
      //static指把方法直接挂在类上,而不是类的实例上面
      static getInstance() {
           //返回一个Demo的唯一实例
           if(!this.instance){
               this.instance = new Demo('dell lee');
           }
           return this.instance;
      }
}

const demo1 = Demo.getInstance();
const demo2 = Demo.getInstance();  //demo2和demo1是一个实例
console.log(demo1.name);
console.log(demo2.name);

十二.抽象类

①抽象类是把类相关的东西抽象出来

abstract class Geom {
    number;
   getType() {
      return 'Gemo';
   }
   abstract getArea(): number;
}

//子类继承自抽象类,必须具体化抽象类中的抽象方法
class Circle extends Geom {
   getArea() {      
       return 123;
   }
}

②接口是把对象等其它东西的通用抽象出来  

interface Person {
  name: string
}

interface Teacher extends Person{
   teachingAge: number;
}

interface Student extends Person{
   age: number;
}

const teacher = {
    name: 'dell',
    teachingAge: 3
}

const student = {
    name: 'lee',
    age: 18
}

const getUserInfo = (user: Person) => {
    console.log(user.name);
};

getUserInfo(teacher);
getUserInfo(student);

注:课程源自慕课网