导学
1.Ts基础语法--2.爬虫功能开发--3.Ts语法进阶--4.项目接口开发---5.TS高级语法--6.项目代码重构--7.项目前端开发--8.总结
知识点:
静态对象 类型注解 类型推断 泛型
类型定义文件 模块化 打包编译 装饰器
Metadata 设计模式 实战问题 ....
前提:
Es6 and Js
Node expressLinkIcon
收获:
应对企业级别动TS项目
在框架层面有更高的理解
扩展技术视野
TypeScript 基础语法入门
TypeScript带来了什么优势
1.开发过程中,发现潜在问题
2.更友好的编辑器自动提示
3.代码语义更清晰易懂
TypeScript基础环境搭建
1.安装node,node -v 查看是否安装成功
2.npm -v 查看是否安装成功
安装ts > npm install -g typescript
node demo.ts 会报错,node无法直接调用ts文件,只能用tsc demo.ts将ts编译生成js 再用node demo.js去执行js文件
// demo.ts
interface Point { x: number, y: number }
function tsDemo(data: Point) {
return Math.sqrt(data.x ** 2 + data.y ** 2);
}
tsDemo({ x: 1, y: 123 });
为了简化这个ts转js 再执行js的这个过程,可以安装ts-node
安装命令:npm install -g ts-node
安装完成后,直接用ts-node demo.ts 即可直接执行demo.ts 不用额外编译生成js
静态类型的深度理解
定义一个静态类型 不仅仅意味着这个变量的类型不能修改,也意味着这个变量的属性 和方法基本也就确定了。
基础类型和对象类型
对基本类型 、对象类型、函数、对象、数组 示例:
可参考掘金上链接学习ts对类型的处理:juejin.cn/post/695005…
函数:返回的是个数字类型的,所以在这里需要标注是number类型,当return如果是string类型或者其他类型就会有提示。
类型注解和类型推断
基本类型相加减 一般会自动分析出类型来,当函数,需要给出类型,具体如下所示:
// type annotation 类型注解, 我们来告诉 TS 变量是什么类型
// type inference 类型推断, TS 会自动的去尝试分析变量的类型
// 如果 TS 能够自动分析变量类型,我们就什么也不需要做了
// 如果 TS 无法分析变量类型的话,我们就需要使用类型注解
// let count: number;
// count = 123;
// let countInference = 123;
// const firstNumber = 1;
// const secondNumber = 2;
// const total = firstNumber + secondNumber;
function getTotal(firstNumber: number, secondNumber: number) {
return firstNumber + secondNumber;
}
const total = getTotal(1, 2);
const obj = {
name: 'dell',
age: 18
};
函数相关类型
函数未必返回我们需要的类型,所以最好也给定义个类型,如下图 如果在return中加上 return first + srcond + '‘,这样 total返回的就是string类型。
在函数add处规范了number类型,如果返回的是string类型,就会有提示。
如果类型是void,那么后面就不应该有返回值
下面这样是可以的,但是如果花括号里加了return就会提示
function sayHello():void{
console.log('hello')
}
function sayHello():void{
return 123 // 会报错
}
如果后面压根就不会执行,那么类型是never。示例如下面代码:
function errorEmitter():nerer{
throw new Error();
console.log(123)// 永远不会执行至此
}
function errorEmitter():nerer{
while(true){}
console.log(123)// 永远不会执行至此
}
解构的语法 如果ts给出类型(后面跟着类型注解 只要是解构,就必须写在后面的花括号里):示例如下
function add({ first, second }: { first: number; second: number }): number {
return first + second;
}
const total = add({ first: 1, second: 2 });
基础语法复习
// 基础类型, boolean, number, string, void, undfined, symbol, null
// let count=123; 这时候count能类型推断出是number类型,
// 当 let count;
// count=123; 放在两行的时候,无法准确推断,这时候 let count会将其推断成any类型
let count: number;
count = 123;
// 对象类型, {}, Class, function, []
// 下面两种方式一样:
// 第一种写法 类型注解 会推断出,返回值就是number类型,所以 func函数 可以不用去写number返回值
const func = (str: string) => {
return parseInt(str, 10);
};
const func1: (str: string) => number = str => {
return parseInt(str, 10);
};
const date = new Date();
// 其他的 case
interface Person {
name: 'string';
}
const rawData = '{"name": "dell"}';
const newData: Person = JSON.parse(rawData);// JSON.parse 不能推断出newData的类型,可以在上面定义个interface
// 如果一个变量可能是number也有可能是string类型,可以使用或
let temp: number | string = 123;
temp = '456';
数组和元组
// 数组
const arr: (number | string)[] = [1, '2', 3];// 每一项既可以是number类型也可以是string类型
const stringArr: string[] = ['a', 'b', 'c'];// 每一项都是string类型
const undefinedArr: undefined[] = [undefined];// 每一项都是undefined,如果不是就会报错
// type alias 类型别名
type User={name:string,age?:number} 类型别名
const objectArr:User[]=[{ // objectArr存储的每一项必须是User类型,
name:'dell',age:28
}]
type User = { name: string; age: number };
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]];
像是csv/excel这种导出的文件,转换为js时候, 可以考虑用元组来进行管理。
interface 接口
有通用性的 可以抽离出 interface
interface 和 type(类型别名)有什么区别?
如果能用interface表述的话就用interface,实在不行 就用type类型别名
当变量声明类型前 加了 readonly,那么这个变量就不能再改写了
// interface 和 type 相类似,但并不完全一致
interface Person {
// readonly name: string;
name: string;
age?: number;
[propName: string]: any;
say(): string;
}
// 老师继承了person的所有属性,再加个teach
interface Teacher extends Person {
teach(): string;
}
// interface 定义函数类型
interface SayHi {
(word: string): 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() { // Teacher 需要有teach方法
return 'teach';
}
};
getPersonName(person);
setPersonName(person, 'lee');
// 类想去应用(implements)接口,需要满足接口的要求,否则会报错
class User implements Person {
name = 'dell';
say() {
return 'hello';
}
}
const say: SayHi = (word: string) => {
return word;
};
类的定义与继承
class Person {
name = 'dell';
getName() {
return this.name;
}
const person = new Person();
console.log(person.getName());
// ts-node demo.ts
// 输出:dell
类的继承,被继承的叫父类 ,继承的 叫 子类。下面 teacher是子类,Person是父类。子类可以对父类的方法进行改写。
class Person {
name = 'dell';
getName() {
return this.name;
}
}
class Teacher extends Person {
getTeacherName() {
return 'Teacher';
}
// getName() {
// return 'lee';
// }
getName() {
return super.getName() + 'lee'; // super相当于Person
}
}
const teacher = new Teacher();
console.log(teacher.getName());
console.log(teacher.getTeacherName());
// ts-node demo.ts
// 输出:
// lee
// Teacher
ts-node demo.ts
// 输出:
dell lee
Teacher
面试:super在编写代码的时候一般用它干嘛?回答出:当我一个类把父类的方法覆盖掉的时候(重写了之后),如果这个时候还想调用父类的方法,那就可以通过super调用父类的方法。这就是super比较常见的一个场景。
类中的访问类型和构造器
private 、protected 、public
// private, protected, public 访问类型
// public 允许我在类的内外被调用
// private 允许在类内被使用
// protected 允许在类内及继承的子类中使用
class Person {
public name: string; // 如果这里改为private name:string;类外调用this.name就会报错
public sayHi() {
this.name;
console.log('hi');
}
private sayABC() {
this.name;
}
}
class Teacher extends Person {
public sayBye() {
this.name(); // 如果上面改为private name:string;这里调用this.name就会报错
}
}
class Person { // 与上面的class Person一样
public name: string;
public sayHi() {
this.name;
console.log('hi');
}
private sayABC() {
this.name;
}
}
const person = new Person();
person.name = 'dell';
console.log(person.name);
person.sayHi();
// constructor
class Person {
// 传统写法
// public name: string;
// constructor(name: string) {
// this.name = name;
// }
// ---下面是上面四行的简写---
// 简化写法
constructor(public name: string) {}
}
const person = new Person('dell');
console.log(person.name);
class Person {
constructor(public name: string) {}
}
class Teacher extends Person {
constructor(public age: number) {
super("法外狂徒"); // 如果不传入name会报错
}
}
const teacher = new Teacher(28); //对应Teacher的age
console.log(teacher.age);
console.log(teacher.name);
// ts-node demo.ts
// 输出:
// 30
// 法外狂徒
静态属性,Setter和Getter
单例模式---静态属性是放在类上的,另外理解单例模式
class Demo {
private static instance: Demo;
private constructor(public name: string) {}
static getInstance() {
if (!this.instance) {
this.instance = new Demo("dell lee");
}
return this.instance;
}
}
const demo1 = Demo.getInstance();
const demo2 = Demo.getInstance();
console.log(demo1.name);
console.log(demo2.name);
抽象类
抽象类只能被继承,不能被实例化
// 抽象类
abstract class Geom {
width: number;
getType() {
return 'Gemo';
}
abstract getArea(): number;
}
new Geom 是不可以的。
下面这样继承是可以的。
class Circle extends Geom {
getArea() {
return 123;
}
}