Typescript基础

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

@


前言

提示:这里可以添加本文要记录的大概内容:

例如:...


一、typescript基础环境搭建

1.安装node.js运行环境
2.使用npm安装typescript(npm install typescript -D)
3.使用npm安装ts-node运行命令(npm install ts-node -D)
4.npm init -y 生成 js的配置文件
5.tsc --init 生成ts的配置文件
6(运行命令(tsc/ts-node)记着带上npx)

...

二、typescript基础语法

1.简介

typescript 基本介绍TypeScript 是由微软开发的一款开源的编程语言,TypeScript 是 Javascript 的超集,遵循最新的 ES6、ES5 规范,TypeScript 扩展了 JavaScript 的语法。TypeScript 更像后端 Java、C#这样的面向对象语言,可以让 JavaScript 开发大型企业项目。谷歌也在大力支持 Typescript 的推广,谷歌的 angular2.x+ 就是基于 Typescript 语法,最新的 Vue 、React 也可以集成 TypeScript。Nodejs 框架中的 Nestjs、midway 中用的就是 TypeScript 语法。

2.基础类型

代码如下(示例):

// any类型
const result:any = 'asd' 

// 数字类型
const a: number = 1

// 布尔类型
const b: boolean = true

// 字符串类型
const c: string = 'lilied'

// 数组类型
const d1: number[] = [1, 2, 3, 4]
const d2: Array<number> = [1, 2, 3, 4]

// 元组类型
const e: [string, number] = ['lilied', 5]

// 枚举类型
enum Target {
    red = 1,
    orange,
    green
}
console.log(Target.red);   // 1
console.log(Target[1]);    // red

enum Local {
    UP = 'UP',
    DOWN = 'DOWN'
}
console.log(Local.UP);       // UP
console.log(Local['UP']);    // UP

// null类型
const f: null = null

// undefined类型
const g: undefined = undefined

// void类型 (一般表示没有返回值)
function h(x: number): void { }

// never 类型 
function error1(): never {
    throw new Error('抛出错误了');
}
function error2(): never {
    while (true) { }
}

// 组合类型
let res: string | number = 1
res = 'lilied'

// 函数类型
const getTotal: (a: number, b: number) => number = (a: number, b: number): number => {
    return a + b
}

// 对象类型
//--------------------------
interface Person {
    name: string;
    age: number;
}
const teacher: Person = {
    name: 'Dell',
    age: 18
}
//--------------------------
class Animal {}
const animal = new Animal()




3.函数相关

代码如下(示例):

// 函数的定义

//1
function getTotal1(a: number, b: number): number {
    return a + b
}
//2
const getTotal2 = function (a: number, b: number): number {
    return a + b
}
//3
const getTotal3 = (a: number, b: number): number => {
    return a + b
}
/*
const getTotal3:(a: number, b: number)=>number = (a: number, b: number):number => {
    return a + b
}
*/

//-----------------------------------------------------------------

// 函数的参数

//1.必选参数
function getInfo1(a: number, b: number) { }
getInfo1(5, 8)

//2.可选参数
function getInfo2(a: number, b?: number) { }
getInfo2(5)
getInfo2(5, 8)

//3.默认参数
function getInfo3(a: number, b: number = 10) { }
getInfo3(5) // a=5 b=10
getInfo3(5, 8) //a=5 b=8

//4.剩余参数
function getInfo4(a: number, ...args: number[]) { }
getInfo4(5, 10, 11, 12) // args:number[] = [10, 11, 12]

// --------------------------------------------------------------

// ts 函数重载
function getInfo(a: string, b: string): string;
function getInfo(a: number, b: number): number;
function getInfo(a: string | number, b: string | number): unknown {
    if(typeof a === 'string' && typeof b === 'string'){
        return a + b
    }else if(typeof a === 'number' && typeof b === 'number'){
        return a + b
    }
}

//可以不用函数重载的例子
//1. 像这样的是参数个数的区别,我们可以使用可选参数来代替函数重载的定义
// function func1 (a: number): number
// function func1 (a: number, b: number): number
function func1 (a: number, b?: number): number ... // 注意第二个参数在类型前边多了一个`?`

//2. 亦或是一些参数类型的区别导致的
// function func2 (a: number): number
// function func2 (a: string): number
// 这时我们应该使用联合类型来代替函数重载
function func2 (a: number | string): number ...

4.数组与元组

代码如下(示例):

// 数组
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 };

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]];

5.接口

代码如下(示例):

5.1 属性类型接口

//对传入对象的属性约束,以下这个是一个属性类型接口
interface FullName {
    firstName: string;
    secondName: string;
    thirdName?: string;
}

function printName(name: FullName) {
    console.log(name.firstName + "--" + name.secondName);
}

//传入的参数必须包含firstName、secondName, (thirdName可以传)
var simpleName = {
    age: 34,
    firstName: '吴',
    secondName: '翔'
};
printName(simpleName);//正确

5.2 函数类型接口

//加密的函数类型接口
interface encrypt {
    (key: string, value: string): string;
}

var md5: encrypt = function (key: string, value: string): string {
    //模拟操作
    return key + "----" + value;
}
console.log(md5("name", "zhangsan"));

var sha1: encrypt = function (key: string, value: string): string {
    //模拟操作
    return key + "====" + value;
}
console.log(sha1("name", "lisi"));

5.3 可索引类型接口

//可索引接口,对数组的约束
interface UserArr {
    [index: number]: string
}
var arr1: UserArr = ["aaa", "bbb"];
console.log(arr1[0]);

//可索引接口,对对象的约束 ****************************重要
interface UserObj {
    [index: string]: string
}
var arr2: UserObj = { name: '张三', age: '21' };
console.log(arr2);

5.4 类类型接口

类类型接口就是对类的约束,它和抽象类抽象有点相似。

interface Animal {
    name: string;
    eat(str: string): void;
}

class Dog implements Animal {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    eat() {
        console.log(this.name + "吃大骨头");
    }
}

var d = new Dog("小狼狗");
d.eat();

class Cat implements Animal {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    eat(food: string) {
        console.log(this.name + "吃" + food);
    }
}

var c = new Cat("小花猫");
c.eat("大老鼠");

5.5 接口的继承

接口可以继承接口,接口之间和抽象类之间的继承都是单向单继承,但是实现接口的子类可以实现多个接口。

简单来说,对于类、抽象类、接口继承只能单继承,但接口却可以多实现。


//人这个接口
interface Person {
    eat(): void;
}

//程序员接口
interface Programmer extends Person {
    code(): void;
}

//小程序接口
interface Web {
    app(): void;
}

//前端工程师
class WebProgrammer implements Programmer, Web {
    // public name: string;
    // constructor(name: string) {
    //     this.name = name;
    // }
    constructor(public name: string){}

    eat() {
        console.log(this.name + "下班吃饭饭")
    }
    code() {
        console.log(this.name + "上班敲代码");
    }
    app() {
        console.log(this.name + "开发小程序");
    }
}

var w = new WebProgrammer("小李");
w.eat();
w.code();
w.app();

6.类(class)相关

6.1 类的定义

// 写法一
// class People {
//     name: string
//     age: number

//     constructor(name: string, age: number) {
//         this.name = name
//         this.age = age
//     }

//     sayHello() {
//         console.log(`I am ${this.name},My age is ${this.age}`);
//     }
// }

//写法二
class People {
    constructor(public name: string, public age: number) {}

    sayHello() {
        console.log(`I am ${this.name},My age is ${this.age}`);
    }
}

function main(){
    const p = new People('lilied', 18)
    p.sayHello()
}

main()

6.2 类的继承

//写法一
/*
class People {
    name: string
    age: number
    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }
    sayHello() {
        console.log(`I am ${this.name},My age is ${this.age}`);
    }
}

class Teacher extends People {
    grade: number
    constructor (name: string, age: number, grade:number) {
        super(name, age)
        this.grade = grade
    }
    sayHello() {
        super.sayHello()
        console.log(`My grade is ${this.grade}`);
    }
}
*/

// 写法二
class People {
    constructor(public name: string, public age: number) { }

    sayHello() {
        console.log(`I am ${this.name},My age is ${this.age}`);
    }
}

class Teacher extends People {

    constructor(public name: string, public age: number, public grade: number) {
        super(name, age)
    }
    sayHello() {
        super.sayHello()
        console.log(`My grade is ${this.grade}`);
    }
}

function main() {
    const teacher:People = new Teacher('lilied', 18, 4)
    teacher.sayHello()
}

main()

6.3 类的访问权限

TypeScript 里面定义属性的时候给我们提供了 三种修饰符:
1.public:公有类型,在当前类里面、子类、类外面都可以访问
2.protected:保护类型,在当前类里面、子类里面可以访问。(在类外部没法访问)
3.private:私有类型,在当前类里面可以访问。(子类、类外部都没法访问)

代码如下(示例):

class Person {
  public name: string = 'lilied';
  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();

6.4 setter与getter,类的静态属性, 单例模式

代码如下(示例):

//getter and setter
/*
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);
*/
// ------------------------------------------------------------------

// static 静态
class Person {
    name: string;              //前面省略了public关键词(实例属性)   
    static sex: string = "男"; //被静态修饰符static修饰的属性(静态属性)

    constructor(name: string) {//构造函数,实例化类的时候触发的方法
        this.name = name;
    }

    run(): void {//实例方法
        console.log(this.name + "在跑步");
    }

    static print(): void {//被静态修饰符static修饰的方法
        // console.log('姓名:' + this.name);//错误
        console.log('性别:' + Person.sex);//正确
        // this.run();//错误
    }
}

Person.print();
//------------------------------------------------------------------------

// 单例模式
class Demo {
    private static instance: Demo;
    private constructor(public name: string) { }

    public 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);

6.5 抽象类,多态代码示例

代码如下(示例):

// 例子一
//动物抽象类,所有动物都会跑(假设),但是吃的东西不一样,所以把吃的方法定义成抽象方法
abstract class Animal {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    abstract eat(): void;//抽象方法不包含具体实现并且必须在派生类中实现
    run() {
        console.log(this.name + "会跑")
    }
}

class Dog extends Animal {
    constructor(name: string) {
        super(name);
    }
    eat(): void {//抽象类的子类必须实现抽象类里面的抽象方法
        console.log(this.name + "吃骨头");
    }
}

class Cat extends Animal {
    constructor(name: string) {
        super(name);
    }
    eat(): void {//抽象类的子类必须实现抽象类里面的抽象方法
        console.log(this.name + "吃老鼠");
    }
}

const d: Animal = new Dog("小狼狗");
const c: Animal = new Cat("小花猫");
d.run();
d.eat();
c.run();
c.eat();

//-------------------------------------------------------------
// 例子二
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);

7.装饰器相关

7.1 类装饰器

// 1。类装饰器

@decorator1
class Person1 { }

function decorator1(constructor: any) {
    console.log('我是一个类装饰器');
}
//--------------------------------------------------

// 2.工厂模式(类装饰器)

@decorator2('我是一个类装饰器(工厂模式)')
class Person2 { }

function decorator2(v: string) {
    return function (constructor: any) {
        console.log(v);
    }
}

// -------------------------------------------------

// 3. 举个例子

@decorator3()
class Person3 { }

function decorator3() {
    return function (constructor: Function) {
        constructor.prototype.name = 'lilied'
        constructor.prototype.getName = (): void => {
            console.log('My name is lilied');
        }
    }
}

const p3 = new Person3()
console.log((p3 as any).name);
console.log((p3 as any).getName());

// ------------------------------------------------------

// 4. 比较完善的写法

@decorator4
class Person4 { }

function decorator4<T extends new (...args: any[]) => any>(constructor: T) {
    return class extends constructor {
        name = 'lilied'
        getName() {
            return this.name
        }
    }
}

const p4 = new Person4()
console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');
console.log((p4 as any).name);
console.log((p4 as any).getName());

// --------------------------------------------------------

// 5. 完善的写法

class Person5 {}

function Decorator() {
    return function <T extends new (...args: any[]) => any>(constructor: T) {
        return class extends constructor {
            name = 'lilied'
            getName() {
                return this.name
            }
        }
    }
}

const Person6 = Decorator()(Person5)

const p6 = new Person6()
console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>');
console.log(p6.getName());
console.log(p6.name);

7.2 方法装饰器

// 方法装饰器
// 普通方法,target 对应的是类的 prototype
// 静态方法,target 对应的是类的构造函数

function getNameDecorator(target: any, key: string, descriptor: PropertyDescriptor) {
    if (key === 'sayHello') {            // 静态方法,target对应的是类的构造函数 (类的构造函数其实就是类本身)
        console.log(target.prototype); 
    } else if (key === 'getName') {     // 普通方法,target 对应的是类的 prototype(原型)
        console.log(target);
    }
    // descriptor.writable = true;
    descriptor.value = function () {    // 改变所有方法的返回值都为decorator
        return 'decorator';
    };
}

class Test {
    name: string;

    constructor(name: string) {
        this.name = name;
    }

    @getNameDecorator
    getName() {
        return this.name;
    }

    @getNameDecorator
    static sayHello() {
        return 'abc'
    }
}

const test = new Test('dell');
console.log(test.getName());  // decorator
console.log(Test.sayHello());  // decorator

7.3 访问器的装饰器

// 访问器的装饰器

function visitDecorator(target: any, key: string, descriptor: PropertyDescriptor) {
    console.log(target);            // 访问器装饰器的 target 对应的是类的 prototype(原型)
    // descriptor.writable = false;
  }
  
  class Test {
    private _name: string;
    constructor(name: string) {
      this._name = name;
    }
    get name() {
      return this._name;
    }
    @visitDecorator
    set name(name: string) {
      this._name = name;
    }
  }
  
  const test = new Test('dell');
  test.name = 'dell lee';
  console.log(test.name);

7.4 属性的装饰器

// 属性的装饰器

// function nameDecorator(target: any, key: string): any {
//   const descriptor: PropertyDescriptor = {
//     writable: false
//   };
//   return descriptor;
// }

// test.name = 'dell lee' 无法修改,报错

// 修改的并不是实例上的 name, 而是原型上的 name
function nameDecorator(target: any, key: string): any {
    target[key] = 'lee';       // 属性装饰器上的 target 也是类的 prototype(原型) 
  }
  
  // name 放在实例上
  class Test {
    @nameDecorator
    name = 'Dell';
  }
  
  const test = new Test();
  console.log((test as any).__proto__.name); // lee
  console.log(test.name)  // Dell

7.5 参数的装饰器

// 参数的装饰器

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);

总结

提示:...

posted @ 2020-09-05 12:07  lilied  阅读(101)  评论(0编辑  收藏  举报