TypeScript学习

一、TypeScript简介

1、TypeScript 是什么?
在这里插入图片描述
2、TypeScript 增加了什么?
在这里插入图片描述
二、开发环境搭建
1、ts需要编译为js,然后才能交给我们js解析器去执行,所以这时候我们要先装一个ts解析器。ts解析器是用node.js写的,所以要先安装node.js。

2、使用npm全局安装typescript

  • 进入命令行
  • 输入:npm i -g typescript

3、创建一个ts文件
4、使用tsc对ts文件进行编译

  • 进入命令行
  • 进入ts文件所在目录
  • 执行命令:tsc xxx.ts

三、TS的类型声明

1、声明一个变量a,同时指定它的类型为number

let a: number;
a = 10;
a = 33;

2、如果变量的声明和赋值是同时进行的,TS可以自动对变量进行类型检测

let c = false;
c = true;

3、声明可以在函数中用,一个是参数类型,一个是返回值类型

function sum(a: number, b: number): number{
	return a + b;
}
let result = sum(123,456)

四、TS中类型
在这里插入图片描述
1、字面量

let a: 10;
a = 10;

可以使用 | 来连接多个类型(联合类型)

let b: "male" | "female";
b = "male";
b = "female";
let c: boolean | string;
c = true;
c = 'hello';

2、any 表示的是任意类型,一个变量设置类型为any后相当于对该变量关闭了TS的类型检测,使用TS时,不建议使用any类型。
any 表示任意类型

// 声明变量如果不指定类型,则TS解析器会自动判断变量的类型为any (隐式的any)
let d;
d = 10;
d = 'hello';
d = true;

unknown 表示未知类型的值

let e: unknown;
e = 10;
e = 'hello';
e = true;

any和unknown两者之间的区别

2.1 any类型的变量,可以赋值给任意变量

// s的类型是string,d的类型是any
let s: string;
let d;
s = d;

2.2 unknown 实际上就是一个类型安全的any

// s的类型是string,e的类型是unknown
let s: string;
let e: unknown;

代码报错

// unknown类型的变量,不能直接赋值给其他变量
s = e;

正确写法

// 做类型判断
if(typeof e === "string"){
	s = e;
}

或者

// 类型断言,可以用来告诉解析器变量的实际类型
/*
* 语法:
* 变量 as 类型
* <类型>变量
**/ 
s = e as string;
s = <string>e;

3、void
void 用来表示空,以函数为例,就表示没有返回值的函数

// 函数返回 number
function(num) : number{
	return 123;
}
// 函数返回 string或number
function(num) : string | number{
	return true;
}
// 函数没有返回值
function(num) : void{
	// return;
	// return undefined;
	// return null;
}

4、never
never 表示永远不会返回结果

function(): never{
	throw new Error('报错了!');
}

5、object
object 表示一个js对象

let a: object;
a = {};
a = function(){};

定义对象结构

// {}用来指定对象中可以包含哪些属性
// 语法:{属性名:属性值,属性名:属性值}
// 在属性名后面加上?,表示属性是可选的
let b: {name: string , age?:number};
b = {name: '孙悟空', age:18};
或者
b = {name: '孙悟空'}
// [propName: string]: any 表示任意类型的属性
let c: {name: string , [propName: string]: any]};
c = {name: '孙悟空' , age: 18, gender: '男'’};

定义函数结构

/*
 * 设置函数结构的类型声明:
 * 语法:(形参:类型,形参:类型 ...)=> 返回值
 * **/
let d: (a:number ,b:number) => number;
d = function (n1,n2): number{
	return n1 + n2;
}

6、array
数组的类型声明:

  • 类型【】
  • Array<类型>
// string[] 表示字符串数组
let e: string[];
e = ['a','b','c'];
// number[] 表示数值数组
let f: number[];
let g: Array<number>;
g = [1,2,3];

7、tuple
元祖,元祖就是固定长度的数组

let h: [string,number];
h = ['hello', 123];

8、enum
枚举

enum Gender{
	Male = 0,
	Female =1
}
let i: {name: string, gender: Gender};
i = {
	name: '孙悟空',
	gender: Gender.Male  // 'male'
}

console.log(i.gender ===  Gender.Male );

&表示同时

let j: {name: string } & { age: number};
j = {name: '孙悟空',age:18};

类型的别名

type myType = 1 | 2 | 3 | 4 | 5;
let k:myType;
let l:myType;
let m:myType;

k = 2;

五、TS编译选项
1、自动编译文件

  • 编译文件是,使用-w指令后,TS编译器会自动监视文件的变化,并在文件发生变化时对文件进行重新编译。
tsc xxx.ts -w

2、自动编译整个项目

  • 如果直接使用tsc指令,则可以自动将当前项目下的所有ts文件编译为js文件
  • 但是能直接使用tsc命令的前提是,要先在项目根目录下创建一个ts的配置文件 tsconfig.json
  • tsconfig.json是一个JSON文件,添加配置文件后,只需要tsc命令即可完成对整个项目的编译

3、tsconfig.json 配置选项

在这里插入图片描述
六、面向对象
1、类(class)
对象中主要包含了两部分: 属性 方法

class Person{
	// 实例属性
	name: string = '孙悟空';
	 // 在属性前面使用static关键字可以定义类属性(静态属性)
	static age: number = 18;

	// 定义方法
	sayHello(){
		console.log('Hello 大家好');
	}
	static sayBye(){
		console.log('拜拜');
	}
}

const per = new Person();
// 实例属性
console.log(per.name);
per.sayHello();

// 静态属性
console.log(Person.age);
Person.sayBye();

2、构造函数和this
this就表示当前对象

class Dog{
	name: string;
	age: number;
	
	// 构造函数
	// 构造函数会在对象创建时调用
	constructor(name: string, age: number) {
		// 在实例方法中,this就表示当前的实例
		// 在构造函数中当前对象就是当前新建的那个对象
		// 可以通过this向新建的对象中添加属性
		this.name = name;
		this.age = age;
	}

	bark(){
		// 在方法中通过this来表示当前调用方法的对象
		console.log(this);
	}
}

const dog = new Dog('小黑',4);
const dog2 = new Dog('小白',2);

dog2.bark();

3、继承

使用继承后,子类将会拥有父类所有的方法和属性

(function (){
	// 定义一个Animal类
	class Animal{
		name: string;
		age: number;

		constructor(name: string, age: number){
			this.name =  name;
			this.age = age;
		}
		
		sayHello(){
			console.log('动物在叫~');
		}
	}
	
	// 定义一个表示狗的类
	// Animal被称为父类,Dog被称为子类
	class Dog extends Animal {
		run(){
			console.log(`${this.name}在跑~~`);
		}
		// 如果在子类中添加了和父类相同的方法,则子类方法会覆盖掉父类方法,这种子类覆盖掉父类的方法,我们称为重写
		sayHello(){
			console.log('汪汪汪汪!);
		}
	}
	
	// 定义一个表示猫的类
	class Cat extends Animal {
		sayHello(){
			console.log('喵喵喵喵!);
		}
	}

	const dog = new Dog('旺财',5);
	const cat = new Cat('咪咪',3);
	console.log(dog);
	dog.sayHello();
	dog.run();
	console.log(cat );
	cat .sayHello();
})();

在这里插入图片描述
4、super关键字
如果在子类中写了构造函数,在子类的构造函数中必须对父类的构造函数调用
super();

class Animal {
	name: string;
	constructor(name: string) {
		this.name = name;
	}
	sayHello(){
		console.log('动物在叫~');
	}
}

class Dog extends Animal{
	age: number;

	constructor(name: string, age: number) {
		// 如果在子类中写了构造函数,在子类的构造函数中必须对父类的构造函数调用
		super(name);
		this.age = age;
	}
	sayHello() {
		// 在类的方法中 super就表示当前类的父类
		// super.sayHello();
		console.log('汪汪汪汪!')
	}
}

const dog = new Dog('旺财',3);
dog.sayHello();

5、抽象类

-以 abstract 开头的类是抽象类
-抽象类中可以有抽象方法,实质方法,真实的属性

// 抽象类不能用来创建对象
// 抽象类是专门用来被继承的类
// 抽象类中可以添加抽象方法
abstract class Animal {
	name: string;
	constructor(name: string) {
		this.name = name;
	}
	// 定义一个抽象方法
	// 抽象方法使用 abstract 开头,没有方法体
	// 抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
	abstract sayHello();
}

class Dog extends Animal{
	sayHello() {
		console.log('汪汪汪汪!')
	}
}

class Cat extends Animal{
	sayHello() {
		console.log('喵喵喵喵!')
	}
}

const dog = new Dog('旺财');
dog.sayHello();

6、接口

-接口定义一个标准,限制某个类必须符合该标准
-接口用来定义一个类结构,用来定义一个类中应该包含哪些属性和方法
-在接口中所有的方法都是抽象方法

//描述一个对象的类型
type myType = {
	name: string,
	age: number
};

interface myInterface{
	name: string;
	age: number;
}

interface myInterface{
	gender: string;
}
	
const obj: myType = {
	name: 'sss',
	age: 111,
	gender: '男'
}

// 接口中所有的属性都不能有实际的值
// 接口只定义对象的结构,而不考虑实际值
interface myInter{
	name: string;
	sayHello():void;
}

// 定义类时,可以使用类去实现一个接口
// 实现接口就是使类满足接口的要求
class MyClass implements myInter{
	name: string;
	constructor(name: string){
		this.name = name;
	}
	sayHello(){
		console.log('大家好~~');
	}
}

7、属性的封装
public:修饰的属性可以在任意位置访问(修改)默认值
private:私有属性只能在类内部进行访问(修改)

class Person{
   // TS 可以在属性前添加属性的修饰符
	private name: string;
	private age: number;

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

	// 定义方法,用来获取name属性
	getName(){
		return this.name;
	}

	// 定义方法,用来设置name属性
	setName(value: string){
		this.name = value;
	}
	
	getAge(){
		return this.age;
	}

	setAge(value: number){
		// 判断年龄是否合法
		if(value >= 0){
			this.age= value;
		}	
	}
}

const per = new Person('孙悟空',18);
// 现在属性是在对象中设置的,属性可以任意的被修改
// 属性可以任意被修改将会导致对象中的数据变得非常不安全
per.setName('猪八戒');
per.setAge(-33);
console.log(per);

-属性存储器
getter 用来读取属性
setter 用来设置属性

// TS中设置getter方法的方式
get name(){
	return this.name;
}

set name(value){
	this.name = value;
}

get age(){
	return this.age;
}

set age(value){
	if(value >= 0){
		this.age = value;
	}
}

const per = new Person('孙悟空', 18);
per.name = '猪八戒';
per.age= -33;
console.log(per);

在这里插入图片描述
protected:受保护的属性,只能在当前类和当前类的子类中访问(修改)

class A{
	protected num: number;
	constructor(num: number){
		this.num = num;
	}
}

class B extends A{
	test(){
		console.log(this.num);
	}
}

const b = new B(123);
b.num = 33;

特殊语法

calss C{
	name: string;
	age: number

	construtor(name: string, age: number){
		this.name = name;
		this.age = age;
	}	
}

//等价于

calss C{
	// 可以直接将属性定义在构造函数中
	constructor(public name: string, public age: number){
	}
}

const c = new C('xxx',111);
console.log(c);

在这里插入图片描述
七、泛型
定义泛型好处,不用指定具体类型而且也能体现出属性和返回参数类型是相同的。

function fn(a: number) :number{
	return a;
}

// 在定义函数或是类时,如果遇到类型不明确就可以使用泛型
function fn<T>(a:T):T{
	return a;
}

let result = fn(10);// 不指定泛型,TS可以自动对类型进行推断
let result2 = fn<string>('hello'); //指定泛型

泛型可以同时指定多个

function fn2<T, K>(a: T,b: K):T{
	console.log(b);
	return a;
}

fn2<number,string>(123,'hello');

有些情况下想要限制泛型范围
接口中有泛型

interface Inter{
	length: number;
}
// T extends Inter 表示泛型T必须实现Inter接口
function fn3<T extends Inter>(a: T): number{
	return a.length;
}

// 正确
fn3('123');
fn3({length: 10});
// 错误
fn3(123);
fn3({name: 'hello'});

类中有泛型

class MyClass<T>{
	name: T;
	constructor(name: T) {
		this.name = name;
	}
}

const mc = new MyClass<string>('yilia');
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值