TypeScript 笔记

发布时间 2023-03-28 21:51:19作者: 悠悠江水

 Date: 2023-03-08 18:35:12
尚硅谷 TypeScript 教程(李立超老师 TS 新课)
TS 没什么难的,一种写法罢了

P1 TS简介

JS 是一种轻量型语言,很难报错,所以很难去写大型项目,维护性很低。有报错难以及时发现,比如写函数类型的参数,无需定义类型。这既是好处也是坏处。
类似于 css 的预处理语言 sass less。需要编译成 js 使用。

TS 增加了什么?

  • 类型 (增加了很多新的数据类型)
  • 支持 ES 的新特性
  • 添加 ES 不具备的新特性
  • 丰富的配置选项
  • 强大的开发工具 (vscode)

P2 开发环境搭建

  • nvm install nodejs
  • npm i -g typescript
  • create xxx.ts document
  • use shell tsc xxx.ts

都是要编译为 js,编辑器不报错即可

P3 TS的类型说明

  let 变量: 类型;
  let 变量: 类型 = 值;
  function fn(参数: 类型, 参数: 类型): 类型{
      ...
  }
  • ts 可以编译任意 js 版本
  • TS 有自动的类型判断机制
  • 当对变量的声明和赋值是同时进行的,TS编译器会自动判断变量的类型
  • 所以如果你的变量的声明和赋值时同时进行的,可以省略掉类型声明

P4-5 TS 中类型

类型

类型 例子 描述
void 空值(undefined) 没有值(或undefined)
never 没有值 不能是任何值
字面量 其本身 限制变量的值就是该字面量的值
object 任意的JS对象
boolean true、false 布尔值true或false
enum enum 枚举,TS中新增类型
tuple [4,5] 元素,TS新增类型,固定长度数组
array [1,2,3] 任意JS数组
number 1, -33, 2.5 任意数字
any * 任意类型
unknown * 类型安全的any
string 'hi', "hi", hi 任意字符串

联合类型

联合取值或类型

类型断言(告诉解析器变量的实际类型)

字面量 就是变量的值
any 可以污染其他变量
unknow 不可以污染其他变量
never 用来报错
object 可在括号内限制元素类型,加 ? 表可选类型
类型的别名

// any 相当于关闭 ts ,用 unknown 替代,不污染其他变量



// void never 设置参数返回值,void 为空,万恶的 undefined ,never 返回报错
function fn(): void {
  throw new Error("错了啊");
}
console.log(fn());

// obj 不常使用,因为 js 都是对象,主要限制其内容类型
// ?表可选
let b: {
  name: string;
  age?: number;
};
b = {
  name: "gavin",
};
// 多个内容,name 为必须,其他随意皆可
let c: { name: string; [propName: string]: unknown };
c = {
  name: "rose",
  sex: 0,
  age: 24,
};
console.log(c);
// 对函数参数限制
let fu: (a: number, b: number) => number;
fu = function (n1: number, n2: number): number {
  console.log(n1, n2);
  return 10;
};
fu(1, 2);
//数组类型
let g: number[] = [1, 2, 3, 4];
console.log(g);

// 元组,固定长度数组 [一个个具体填]
let h: [string, number] = ["Gavin", 25];
console.log(h);
// enum 枚举 可能情况全部列出来
enum Gender {
  Male,
  Female,
}
let i: { name: string; gender: Gender } = { name: "阿强", gender: Gender.Male };
console.log(i);
// `|`或                   /// `&` 都
let j: string | number = 1;

// 类型别名,选一个吧。
type myType = 1 | 2 | "a";
let m: myType = 2;
console.log(m);

P13. 面向对象

类,用于创建具体对象的模板。

定义类

class cityClass {
  bj:string;
  constructor(abc:number){
    this.bj=abc
  }
}


P14. 构造函数和 this

和 js 类一样,只不过加了个类型定义
static 静态属性 在类里定义,可以直接通过类名调用
readonly 只读属性,只有实例化后才能调用
new 是将类实例化

类跟对象一样,只不过类的目的是创造对象

class Person {
  name: string = "gavin";
  static sex: number = 1; // 静态属性
  readonly age: number = 18; // 只读属性
  static sayBye() {
    console.log("bye");
  }
}
const per = new Person();
console.log("per-------" + per);
console.log("person-------" + Person.age);
Person.sayBye()

P15. 继承

每次创建的狗不同。用构造器生成多个不同的对象

class Dog{
  name: string;
  age:number
  constructor(name:string,age:number) {
    console.log("当前实例" + this);
    this.name = name
    this.age =age
  }
  bark() {
    console.log(this);
  }
}
const dog = new Dog("aa",8);
const dog2 = new Dog("bb",6);
console.log(dog);
console.log(dog2);

P16 继承

两个类几乎一样。重复代码提取出来。写在父类里进行复用。
子类想加新的方法、在子类里写即可

方法重写,在子类中写父类同名的不同功能方法。

class Animal{
  name: string;
  age:number
  constructor(name:string,age:number) {
    this.name = name
    this.age =age
  }
  bark() {
    console.log("动物叫");
  }
}
class Dog extends Animal{
  run() {
    console.log(this.name+"在跑");
  }
  bark() {
    console.log("狗叫中~~~~~");
  }
}
class Cat extends Animal{
}
const dog = new Dog("单身狗",25);
const cat = new Cat("傲娇猫", 18);
dog.run();
dog.bark();
cat.bark();

P18-19. super 关键字、抽象类(abstract)

抽象类 在 复用类的类 使用 abstract 进行修饰,禁止实例化
类的抽象方法,子类必须重新,不然报错。

super 关键字,子类写构造函数时,父类会被自动覆盖,触发函数重写
如果想要用父类的构造函数。则使用super关键字进行调用。实现构造函数合并的目的。

abstract class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  abstract bark(): void;
}
class Dog extends Animal {
  age: number;
  constructor(name: string, age: number) {
    super(name);
    this.age = age;
    console.log("这狗的岁数" + age);
  }
  bark(): void {
    console.log(this.name+"在叫!!!!!!!!");
  }
}
const dog = new Dog("旺财", 18);
dog.bark();


P19. 接口

写起来比较麻烦,接口即规范,就是对类的限制,跟ts类型 对 Obj 的限制是差不多的

type personType = {
  name: string;
  sex: number
}

const per: personType = {
  name: "gavin",
  sex:1
}
console.log(per);

// 接口用来定义类的结构
// 可定义多个同名借口,属性添加
interface carBrand{
  name: string;
  history: number
}
interface carBrand{
  country:string
}
const car: carBrand={
  name: "大众",
  history: 200,
  country:"Germany"
}
interface myInt{
  name: string,
  sayBye(): void;
}

class MyInt implements myInt{
  name: string;
  constructor(name: string) {
    this.name=name
  }
  sayBye(): void {
      console.log(this.name+"---再见");
  }
}
const imInt = new MyInt("gavin");
imInt.sayBye()

P20. 属性的封装(private 私有属性)

通过方法获取私有属性
private 在 class 使用存取器 get set 进行修改。只能在这个类中使用,不太常用
public 继承子类也可访问,
protected
将属性声明直接定义在构造函数中,写起来方便

class Person {
  private _name: string;
  private _age: number;
  constructor(name: string, age: number) {
    this._name = name;
    this._age = age;
  }
  getAge() {
    return this._age;
  }
  setAge(val: number) {
    if (val > 0) {
      return (this._age = val);
    }
  }
  // 存取器形式
  get name() {
    return this._name;
  }
  set name(val: string) {
    this._name = val
  }
}
const per = new Person("a", 18);

// console.log(per._age); //不可访问
console.log(per.getAge());
per.setAge(0);
console.log(per.getAge());

console.log(per.name);
console.log(per.name="猪八戒");

class T {
  constructor(public name: string, public age: number) {}
}

const t =new T("张三", 18);
console.log(t.name);

P21. 泛型

泛型可以在多处使用

// 类型不明确用泛型
function fn<T>(a: T): T {
  return a;
}
fn(5); //不指定
fn<string>("hello");

function fn2<T, K>(a: T, b: K): T {
  console.log(a, b);
  return a;
}
fn2(5, "hello");
fn2<number, string>(5, "hello");

// 限制泛型范围 (泛型返回为类)
interface Inter {
  length: number;
}
function fn3<T extends Inter>(a: T): number {
  console.log(a);
  return a.length;
}
fn3("123");