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.tsdocument - 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");