目录:
一、环境配置
二、ts的类型
三、ts中的函数
四、ts中的接口定义
五、ts中的泛型
六、ts中的命名空间
七、ts中的装饰器
环境配置
1、全局安装typescript:npm i -g typescript
2、在cmd中进入到ts文件夹内,运行tsc --init,创建tsconfig.json文件,修改文件里的outDir选项(生成的js文件的地址)
3、在vsCode中选择终端->运行任务->监视tsconfig.json,ts文件变化时会自动生成对应的js文件
typesrcipt类型:
1、分类:布尔类型:boolean、数字类型:number、字符串类型:string、数组类型:array、元组类型:tuple、枚举类型enmu、任意类型:any、undefined和null、void类型、never类型
2、语法:变量名:类型 = 赋值
let b: boolean = true;
// b = "ss"; //赋值其他类型的值时会报错
let s: string = "string";
let n: number = 2;
console.log(b, s, n);
//数组类型
let arr: number[] = [1, 2];
let arr1: Array<number> = [1, 2]; //第二种写法
//元组类型:是array类型中的一种,给每一个元素指定一个类型
let t: [number, string] = [1, "1"]; //必须一一对应
let t1: any[] = [1, "s", true]; //元素可以为任意类型
console.log(arr, t);
//枚举类型,如果不给元素赋值则它的值为对应的下标(下标从0开始),如果某项赋值了,并且为整数,则其后面的选项会在此值上累加,如果是非整数,则其后面的元素必须赋值,否则会报错
enum Color {
blue,
green = 3,
red
}
//enum Color {blue,green='green',red}; //报错
let bc: Color = Color.blue;
let gc: Color = Color.green;
let rc: Color = Color.red;
console.log(bc);
console.log(gc);
console.log(rc); //green的值被初始化为3,则red对应累加,变成4
//any类型,相当于放弃了ts的类型检查,可以随意转化类型
var a: any = { a: "aa" };
a = "sss";
console.log(a);
//undefined和null,定义变量但未赋值时使用,可以给一个变量设置多个类型
var n: number | undefined | null; //num可能为number类型,可能是undefined,也可能是null
n = 22;
console.log(n);
//void类型:表示没有任何类型,一般用于没有返回值的方法
function voidFn(): void {
console.log("voidFn");
}
voidFn();
ts中的函数
1、指定参数的类型,可以设置默认值,可以设置是否可选
2、指定返回值的类型
function run(name: string, age: number): string {
return name + ":" + age + "岁";
}
console.log(run("张三", 22));
//使用?来设置是否可选,可选参数必须放置在必选参数之后
function run(age: number, name?: string): string {
return name ? name + age : "陌生人" + age;
}
console.log(run(20, "张三")); //张三
console.log(run(20)); //陌生人
//设置默认值
function run(name: string = "默认名字"): string {
return name;
}
console.log(run("张三")); //张三
console.log(run()); //默认名字
ts中的接口定义:使用interface关键字
1、接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类里必须提供某些方法
2、属性类接口
3、函数类型接口
4、类类型接口
5、接口的继承
//属性类接口
//iPerson接口必须有name(string类型)属性,可以有age(number类型)属性
interface iPerson {
name: string;
age?: number;
}
let person: iPerson = {
name: "张三",
age: 20
// sex: "man" //报错,接口中没有sex属性
};
console.log(person);
//TIPS:如果不能确定最后的传参是否比接口有更多的参数,可以使用'字符串索引签名'([propName: string])来绕开多余参数的检查
interface iPerson {
name: string;
age?: number;
[propName: string]: any; //定义了属性名为string类型,属性值为any类型
}
let person: iPerson = {
name: "张三",
age: 20,
sex: "man" //使用了字符串索引签名,不会报错
};
console.log(person);
//函数类型接口
// iFn接口定义了参数和返回值规范
interface iFn {
(name: string, age?: number): string;
}
let man: iFn = function(name: string, age?: number): string {
let n = "man" + name;
return age ? n + age : n;
};
let woman: iFn = function(name: string, age?: number): string {
let n = "woman" + name;
return age ? n + age : n;
};
console.log(man("张三"));
console.log(woman("韩梅梅"));
//类类型接口,约束类的属性和方法
//定义了iPerson接口,必须包含name、age属性和setAge方法
interface iPerson {
name: string;
age: number | undefined;
setAge(age: number): void;
}
//使用关键字implements,Person类必须满足iPerson接口的格式
class Person implements iPerson {
name: string;
age: number | undefined; //未在初始化时给age赋值,所以age的类型需要加上undefined
constructor(name: string) {
this.name = name;
}
setAge(age: number) {
this.age = age;
}
}
let p = new Person("张三");
p.setAge(20);
console.log(p);
//接口的继承,使用extends关键字
interface iPerson {
name: string;
}
interface iMan extends iPerson {
sex: string;
}
let m: iMan = {
name: "张三",
sex: "man"
};
console.log(m);
ts中的泛型,使用<>来定义泛型
1、当没有办法确定数据类型时,除了用any(any相当于放弃了数据类型检查),还可以使用泛型。泛型就是解决对不确定数据类型的支持,在调用时才确定数据类型
2、方法中的泛型
3、类中的泛型
4、接口中的泛型
5、作为参数的泛型类
//方法中的泛型,在调用时才确定T的类型
//test方法,规定了传入的参数和函数返回值都是T的类型
function test<T>(value: T): T {
return value;
}
console.log(test<number>(20)); //T为number类型,则传入的值和返回值也要为number类型
console.log(test<string>("s")); //T为string类型
// test<number>('s'); //错误,传入的值不是number类型
//类中的泛型,在创建Test实例时确定T的数据类型
class Person<T> {
names: T[] = [];
add(value: T): void {
this.names.push(value);
}
}
var p = new Person<string>(); //规定了T为string类型,则Person类中所有的T都要为string类型
p.add("张三");
p.add("李四");
p.add("韩梅梅");
console.log(p);
//在接口中的泛型
interface iPerson<T> {
name: string;
data: T;
}
interface iBaseInfo {
age: number;
sex: string;
}
let p: iPerson<iBaseInfo> = {
//泛型T的类型为iBaseInfo,因此data的数据结构必须符合接口iBaseInfo的结构
name: "张三",
data: {
age: 20,
sex: "man"
}
};
console.log(p);
//作为参数的泛型类
class User {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
class People<T> {
list: T[] = [];
add(p: T): void {
this.list.push(p);
}
}
let p = new People<User>(); //把user类作为参数传给People类,People的泛型为user,所以add传的参数只能是User类型
let u = new User("张三", 20);
p.add(u);
console.log(p);
ts中的命名空间
1、使用namespace关键字定义命名空间
2、命名空间内的变量是私有的,如果要访问,需要使用export导出
namespace nPerson {
interface iN {
name: string;
}
export class People {
name: iN;
constructor(name: iN) {
this.name = name;
}
}
}
var p = new nPerson.People({ name: "张三" });
console.log(p);
ts中的装饰器,使用@使用装饰器,装饰器必须放在被装饰的前面,并且不能加分号
1、装饰器是一种特殊类型的声明,它能够被附加到类声明、方法、属性、参数上,以此改变他们的行为。通俗地讲,装饰器就是一个方法,可以注入到类、方法、属性参数上来扩展他们的功能。
2、装饰器的分类:普通装饰器(无法传参),装饰器工厂(可传参,一般使用这种)
3、类装饰器
4、属性装饰器
5、方法装饰器
6、参数装饰器
//类装饰器:类装饰器在类声明之前被声明(紧挨着类声明),类装饰器应用于类构造函数,可以在不修改类的前提下拓展类的功能
function logClass(param: string) {
return function(target: any) {
//target指向类
//拓展属性
target.prototype.sex = param;
//拓展方法
target.prototype.getSex = function() {
console.log(this.sex);
};
};
}
//属性装饰器:属性装饰器表达式会在运行时当做函数被调用,传入2个参数:1、对于静态成员来说是类的构造函数,对于实例成员是类的原型对象,2、属性名
function logProperty(param: number) {
return function(target: any, attr: any) {
target[attr] = param; //修改了target下的attr属性的值
};
}
//方法装饰器:它会被应用到方法的属性描述符上,可以用来监视、修改、替换方法定义,传入3个参数:1、对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象。2、方法名。3、成员的属性描述
function logMethod(param?: any) {
return function(target: any, name: string, desc: any) {
//修改原方法
var oMethod = desc.value;
desc.value = function(...args: any[]) {
console.log(param);
return oMethod.apply(this, args); //继续执行原方法里的代码
};
};
}
//参数装饰器:参数装饰器表达式会在运行时当做函数被调用,可以使用参数装饰器为类的原型增加一些元素数据,传入3个参数:1、对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象。2、方法的名字。3、参数在函数参数列表中的索引位置。
function logParam(param?: any) {
return function(target: any, methodName: string, paramIndex: number) {
console.log("logParam:::", target);
console.log("logParam:::", methodName);
console.log("logParam:::", paramIndex);
};
}
@logClass("man")
class People {
@logProperty(22)
age: number | undefined;
name: string;
constructor(name: string) {
this.name = name;
}
@logMethod("方法装饰器")
getName(): string {
return this.name;
}
setName(@logParam("获取参数") name: string) {
this.name = name;
}
}
let p: any = new People("张三"); //变量p需定义为any类型,否则获取装饰器里的属性和方法时会报错
console.log(p.age);
p.getSex();
console.log(p.getName()); //p.getName()的值为方法修饰器方法里返回的值
p.setName("李四");
console.log(p.name);