Typescript 学习
⦁ 基础语法
安装: typescript全局安装 ts-node全局安装
编译:tsc demo1.ts 生成js文件
初始化: tsc –init 生成tsconfig.json
使用:ts-node index.ts
并行命令:concurrently插件
打包工具: parcel
插件: reflect-metedata
⦁ Typescript是静态类型
⦁ 数组
⦁ const numbers: number[] = [1, 2, 3];
⦁
⦁ const arr: (string|number)[] = [1,2,'3'];
1.3 interface
interface Pointer {
x: number,
y: number
}
function demo2(data: Pointer){
console.log(data.x)
}
demo({ x: 1, y: 2 });
const date: Date = new Date();
1.4 函数参数类型
function demo(data: { x: number; y: number }) {
console.log('hahah');
return Math.sqrt(data.x ** 2 + data.y ** 2);
}
1.5 对象类型
const teacher: {
name: string;
age: number;
isSave: boolean;
} = {
name: 'lisi',
age: 18,
isSave: false,
};
1.6 基础类型:number, string, null, undefined, symbol, boolean, void
1.7 对象类型:函数类型 类类型
class Person {}
const tescher: Person = new Person();//类类型
const getTotal: () => number = () => 3;//函数类型,返回数字
1.8 类型推断与类型注解
// type annotation 类型注解, 我们来告诉 TS 变量是什么类型
// type inference 类型推断, TS 会自动的去尝试分析变量的类型
// 如果 TS 能够自动分析变量类型,我们就什么也不需要做了
// 如果 TS 无法分析变量类型的话,我们就需要使用类型注解
1.9 函数返回值
function getNum(first: number, second: number): number{
return first + second;
}
function say(): void {
console.log('哈哈哈');
}
function errEmiteer(): never {//表示函数永远不可能执行完
throw new Error();
console.log(222)
}
function errEmiteer(): never {
//表示函数永远不可能执行完
while (true) {}
console.log(222);
}
function add({ first, second }:
{ first: number; second: number }): number {
return first + second;
}
function getNumber({ first }: { first: number }) {
return first;
}
const total2 = add({ first: 1, second: 2 });
const count = getNumber({ first: 1 });
const func = (str: string): number => {
return parseInt(str);
}
1.10 针对那些系统内置的方法,对返回值进行类型注解
interface Person1 {
name: string
}
const newStr = "{'name': 'cmd'}";
const p: Person1 = JSON.parse(newStr);
1.11 数组与元组
1..11.1 对象数组
const obj2: { name: string }[] = [{ name: 'haha' }];
1.11.2 类型别名
// type alias 类型别名
type User = {
name: string;
age: number;
};
const obj: User[] = [{ name: 'heheh', age: 2 }];
1.11.2 类数组
class Teacher1 {
readonly name: string;//表示只读属性,不能赋值
age: number;
}
const objectA: Teacher1[] = [
new Teacher1(),
{
name: 'dell',
age: 28,
},
];
1.11.3 元组(处理csv文件很方便)
const trach: [string, string, number] = ['Dell', 'female', 19];
const teacherList: [string, string, number][] = [['dell', 'male', 19], ['sun', 'female', 26], ['jeny', 'female', 38]];
1.11.4 interface 可以定义数组索引、函数、类
类型别名跟接口差不多,区别: type可以代表string; interface 只能代表函数或对象,无法代表string; 一般使用接口,实在不行在使用类型别名
interface Person {
name: string;
age?: number;//问号表示可有可无
[propName: string]: any; //表示还可以有其他属性
say(): string;//say方法
}
getPersonName({//这种直接传的方式,传的内容必须是Person里面的
name: '哈哈',
});
let person = {
name: '哈哈',
age: 1,
sex: 'femal'
}
getPersonName(person);//这种通过变量传递的方式,ts校验没有那么严格,可以有其他属性
类实现接口:
class User2 implements Person {
name = 'dell';
say() {
return 'hello';
}
}
接口继承接口:
interface Person {
name: string;
age?: number;
[propName: string]: any; //表示还可以有其他属性
say(): string;
}
interface Teach extends Person{
teacg(): string
}
interface SayHi {
//接口代表函数
(word: string): string;
}
const say: SayHi = (word: string) => { return word}
super调用父类的方法
class Person {
name = 'dell';
getName() {
return this.name;
}
}
class Teacher extends Person {
getTeacherName() {
return 'Teacher';
}
getName() {
return super.getName() + 'lee';
}
}
const teacher = new Teacher();
console.log(teacher.getName());
console.log(teacher.getTeacherName());
private protected public
// private, protected, public 访问类型
// public 允许在类的内外被调用
// private 允许在类内被使用
// protected 允许在类内及继承的子类中使用
// class Person {
// public name: string;
// public sayHi() {
// this.name;
// console.log('hi');
// }
// private sayABC() {
// this.name;
// }
// }
// class Teacher extends Person {
// public sayBye() {
// this.sayHi();
// }
// }
// 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('dell');
}
}
const teacher = new Teacher(28);
console.log(teacher.age);
console.log(teacher.name);
super()表示调用父类的构造函数;super.name或方法表示调用父类的属性或方法
setter跟getter使用
class Person3 {
constructor(public _name: string) {}
get name() {
return this._name;
}
set name(val: string) {
this._name = val;
}
}
let prrson = new Person3('hahaah');
console.log(prrson.name); //获取名字
prrson.name = 'ooo'; //设置名字
console.log(prrson.name);
设计模式之单例模式
class Demo {
private static instance: Demo;
constructor(public name: string){};
static getInstace(){
if(!this.instance){
return new Demo('ll');
}
return this.instance
}
}
Let demo1 = Demo.getInstance();
1.11.5 抽象类
abstract class Geom {
width: number;
getType() {
return 'Gemo';
}
abstract getArea(): number;
}
class Circle extends Geom {
getArea() {
return 123;
}
}
class Square {}
class Triangle {}
接口
interface Person {
name: string;
}
interface Teacher extends Person {
teachingAge: number;
}
interface Student extends Person {
age: number;
}
interface Driver {
name: string;
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);
2 爬虫
插件:@types/superagent: 爬虫superagent cheerio @types/cheerio
.d.ts文件的作用,让ts识别js文件
3.1 类型断言
interface Bird {
fly: boolean;
sing: () => {};
}
interface Dog {
fly: boolean;
bark: () => {};
}
//类型保护
function tranAnimal(animal: Bird | Dog) { //联合类型
if (animal.fly) {
(animal as Bird).sing(); //断言
} else {
(animal as Dog).bark();
}
}
//类型保护
function tranAnimal2(animal: Bird | Dog) {
//联合类型
if ('sing' in animal) {
animal.sing();
} else {
animal.bark()
}
}
class NumObj {
count: number;
}
//使用instanceof 来做类型保护
function add(first: object | NumObj, second: object | NumObj) {
if (first instanceof NumObj && second instanceof NumObj) {
return first.count + second.count;
}
return 0;
}
//使用typeof 来做类型保护
function add2(first: string | number, second: string | number) {
if (typeof first === 'string' && typeof second === 'string') {
return first + second;
}
return 0;
}
3.2 枚举类型 默认下表从0开始,可以字典一下标,默认后面一个比前面一个大1
enum Status{ green = 1, yellow = 4, red}
console.log(Status.green);//1
console.log(Status.yellow);//4
console.log(Status.red);//5
console.log(Status[0]);//undefined
console.log(Status[5]);//red
3.3 函数泛型 generic
// 泛型 generic
function join<ABC>(first: ABC, second: ABC) {
return `${first} ${second}`;
}
join<number>(1, 3);
join<string>('1', 3 + '');
join(1, 2)
function map<ABC>(params: Array<ABC>) {
return params;
}
map<string>(['abc']);
map([2,3]);
泛型可以继承
interface Item {
name: string;
}
class DataManager<T extends Item> {
constructor(private data: T[]) {}
getItem(index: number): string {
return this.data[index].name;
}
}
const data = new DataManager([
{
name: 'dell',
},
]);
// 如何使用泛型作为一个具体的类型注解
function hello<T>(params: T) {
return params;
}
const func: <T>(param: T) => T = hello;
3.4 namespace 命名空间
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();
}
}
}
///<reference path="components.ts" />
//依 赖关系 命名空间相互引用
namespace Home {
export namespace Dell {
export const teacher: Components.user = {
name: 'dell'
};
}
export class Page {
constructor() {
new Components.Header();
new Components.Content();
new Components.Footer();
new Components.Footer();
}
}
}
4.5 parcel打包
4.6 .d.ts 描述文件
// 定义全局变量
// declare var $: (param: () => void) => void;
// 定义全局函数
interface JqueryInstance {
html: (html: string) => {};
}
declare function $(readyFunc: () => void): void;
declare function $(selector: string): JqueryInstance;
declare function $(
params: string
): {
html: (html: string) => {};
};
interface Jquery {
(readyFunc: () => void): void;
(selector: string): JqueryInstance
}
declare var $: Jquery;//实现函数重载
// 如何对对象类型进行定义 以及对类进行定义以及命名空间的潜逃
declare namespace $ {
namespace fn {
class init {}
}
}
ES6 模块化
// Es6 模块化
declare module 'jquery' {
interface JqueryInstance {
html: (html: string) => JqueryInstance;
}
// 混合类型
function $(readyFunc: () => void): void;
function $(selector: string): JqueryInstance;
namespace $ {
namespace fn {
class init {}
}
}
export = $;
}
4.7 泛型keyof的使用
interface Person {
name: string;
age: number;
gender: string;
}
// type NAME = 'name';
// key: 'name';
// Person['name'];
// type T = 'age'
// key: 'age'
// Person['age']
// type T = 'gender'
// key: 'gender'
// Person['gender']
class Teacher {
constructor(private info: Person) {}
getInfo<T extends keyof Person>(key: T): Person[T] {
return this.info[key];
}
}
const teacher = new Teacher({
name: 'dell',
age: 18,
gender: 'male'
});
const test = teacher.getInfo('name');
console.log(test);
type Name = ‘name’ ;//类型·可以是字符串
⦁ 装饰器
装饰器本身是一个函数
⦁ 类的装饰器
// 装饰器会在类创建完就执行,而不是实例化时才执行
function testDecorator(constructor: any) {
//类的装饰器接收到的是构造函数
console.log('decorator');
constructor.prototype.getName = () => {
console.log('dell');
};
}
@testDecorator
class Test {}
const test = new Test();
(test as any).getName();
// 装饰器会在类创建完就执行,而不是实例化时才执行
function testDecorator() {
//类的装饰器接收到的是构造函数
console.log('decorator');
return function (constructor: any) {
constructor.prototype.getName = () => {
console.log('lily');
};
};
}
@testDecorator()
class Test2 {}
const test2 = new Test2();
(test2 as any).getName();
// 装饰器会在类创建完就执行,而不是实例化时才执行
function testDecorator3<T extends new (...args: any[]) => any>(constructor: T) {
return class extends constructor {
name = 'dddd';
getName() {
return this.name;
}
};
}
@testDecorator3
class Test3 {
name: string;
constructor(name: string) {
this.name = name;
}
}
const test3 = new Test3('haha');
console.log((test3 as any).getName());
// 装饰器会在类创建完就执行,而不是实例化时才执行
function testDecorator() {
return function <T extends new (...args: any[]) => any>(constructor: T) {
return class extends constructor {
name = 'dddd';
getName() {
return this.name;
}
};
};
}
const Test = testDecorator()(
class {
name: string;
constructor(name: string) {
this.name = name;
}
}
);
const test4 = new Test('dddd');
console.log(test4.getName());
⦁ 方法装饰器
function getNameDecorator(
target: any,
key: string,
descriptor: PropertyDescriptor
) {
console.log(target, key);
console.log(descriptor);
descriptor.writable = false; //不让getName被修改
descriptor.value = function () {
//修改装饰方法的返回值
return 'descriptor';
};
}
class Test {
name: string;
constructor(name: string) {
this.name = name;
}
@getNameDecorator
getName() {
return this.name;
}
}
const test = new Test('namedel');
console.log(test.getName());
⦁ 访问器的装饰器
function setNameDecorator(
target: any,
key: string,
descriptor: PropertyDescriptor
) {
console.log(target, key);
console.log(descriptor);
// descriptor.writable = false; //不让getName被修改
// descriptor.value = function () {
// //修改装饰方法的返回值
// return 'descriptor';
// };
}
class Test {
private _name: string;
constructor(_name: string) {
this._name = _name;
}
get name() {
return this._name;
}
@setNameDecorator
set name(val) {
this._name = val;
}
}
const test = new Test('namedel');
console.log(test.name);
test.name = 'hahah';
console.log(test.name);
⦁ 属性的装饰器
function nameDecorator(target: any, key: string) {
console.log(target, key);
// console.log(descriptor);
// const descriptor: PropertyDescriptor = {
// writable: false,
// };
// 修改的不是实力上的name 而是原型上的name
target[key] = 'nageh';
// return descriptor;
}
class Test {
@nameDecorator
name = 'hahah';
}
const test = new Test();
console.log(test.name);
⦁ 参数的装饰器
// 原型,方法名,参数所在的位置
function paramDecorator(target: any, method: string, paramIndex: number) {
console.log(target, method, paramIndex);
}
class Test {
getInfo(name: string, @paramDecorator age: number) {
console.log(name, age);
}
}
const test = new Test();
test.getInfo('Dell', 30);
⦁ 实战小例子
const userInfo: any = undefined;
function catchError(msg: string) {
return function(target: any, key: string, descriptor: PropertyDescriptor) {
const fn = descriptor.value;
descriptor.value = function() {
try {
fn();
} catch (e) {
console.log(msg);
}
};
};
}
class Test {
@catchError('userInfo.name 不存在')
getName() {
return userInfo.name;
}
@catchError('userInfo.age 不存在')
getAge() {
return userInfo.age;
}
@catchError('userInfo.gender 不存在')
getGender() {
return userInfo.gender;
}
}
const test = new Test();
test.getName();
test.getAge();