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);
总结
提示:...