安装
npm install typescript -D
生成配置文件:tsconfig.json
npx tsc --init
ts中的数据类型
- boolean:布尔
- number:数字
- string:字符串
- array:数组
- tuple:元组
- enum:枚举
- any:任意类型
- null 和 undefined
- void
- never
数据类型定义方法
定义原始类型
boolean、number、string
const flag: boolean = false;
定义数组类型
第一种方式:
const sArr: string[] = ['1', 'dhdh'];
let nArr: number[] = [1, 2, 10];
// 定义任意类型的数组
let aArr: any[] = ['dd', 123];
第二种方式(使用泛型):
let arr: Array<number> = [1, 45, 67];
let arr: Array<any> = ['dd', 123];
定义元组类型
属于数组的一种,定义数组中每一项的类型
let arr: [string, number, boolean] = ['哈哈', 23, false];
定义枚举类型
如果给枚举类型赋值了,使用的是赋值的数据
enum Flag {
success = 1,
error = -1
}
let flag: Flag = Flag.success; // 1
如果没有给枚举类型赋值,使用的是索引值(index)
enum Color {
red, blue, orange
}
let a: Color = Color.red; // 0
let b: Color = Color.blue; // 1
let c: Color = Color.orange; // 2
如果给其中某写枚举值赋值了,其他一些枚举值没有赋值,后面的枚举值会在前面已经定义的枚举值基础上递增
enum Color {
red,
blue = 5,
orange
}
let a: Color = Color.red; // 0
let b: Color = Color.blue; // 5
let c: Color = Color.orange; // 6
定义任意类型
let num: any = 123;
num = '456';
num = false;
定义 null 和 undefined 类型
其他(never类型)数据类型的子类型
var num: undefined;
console.log(num);
var num: number | undefined;
num = 123;
console.log(num);
定义 void 类型
一般用于定义没有返回值的方法
function run(): void {
console.log('我没有return哦');
}
定义其他类型(never)
是其他类型(包括 null 和 undefined)的子类型,表示从不会出现的值。
这个类型基本不会用到。
var a: undefined;
a = undefined;
var a: never;
a = (() => {
throw new Error('报错');
})();
函数的定义
定义返回值
function run(): string {
return 'haha';
}
const fun = function(): number {
return 123;
}
定义传参
function run(name: string, age: number): string {
return `${name}--${age}`;
}
const fun = function(name: string, age: number): string {
return `${name}--${age}`;
};
// 加上 ? 表示可选参数,可传可不传
// 【注意】可选参数必须放在参数的最后面!!!
const fun2 = function(name: string, age?: number): string {
if (age) {
return `${name}--${age}`;
} else {
return `${name}--保密`;
}
};
// 默认参数
const fun3 = function(name: string, age: number = 20): string {
if (age) {
return `${name}--${age}`;
} else {
return `${name}--保密`;
}
};
// 剩余参数
const fun4 = function(a, b, ...rest:number[]): void {
let sum = 0;
for (let i = 0; i < rest.length; i++) {
sum += rest[i];
}
console.log(a, b, sum);
};
fun4(1, 2, 3, 4); // 1 2 7
// 函数重载
function getInfo(age: number): string;
function getInfo(name: string): string;
function getInfo(str: any):any {
if (typeof str === 'number') {
return `我今年${str}岁`;
}
return `我叫${str}`;
}
getInfo(12); // 我今年12岁
getInfo('明明'); // 我叫明明
// 报错,因为没有定义 boolean 类型
// getInfo(false);
ts中的类
类的定义
class Person {
name: string; // 属性 前面省略了public关键词
constructor(name: tring) {
this.name = name;
}
getName(): void {
console.log(this.name);
}
setName(name: string): void {
this.name = name;
}
}
const p = new Person('张三');
p.getName(); // 张三
p.setName('李四');
p.getName(); // 李四
继承:extends + super
class Person {
name: string; // 属性 前面省略了public关键词
constructor(name: tring) {
this.name = name;
}
run(): string {
return this.name;
}
}
class Web extends Person {
constructor(name: string) {
super(name);
}
}
const w = new Web('张三');
w.run(); // 张三
类里面的修饰符
public、protected、private
属性的修饰符默认是公有(public)。
ts中的接口
使用 interface
关键字定义接口。
属性接口
interface FullName {
firstName: string;
secondName: string;
}
function printName(name: FullName) {
console.log(name.firstName + '--' + name.secondName);
}
// 这种写法不允许对象中传入多余的属性
printName({
firstName: '张',
secondName: '三',
})
// 待确认?:可以传入其他的属性
const obj = {
age: 18,
firstName: '张',
secondName: '三',
};
printName(obj);
可选属性
interface FullName {
firstName: string;
secondName: string;
// 可选属性
age?: number;
}
function getName(name: FullName) {
console.log(name.firstName + name.secondName + name.age);
}
getName({
firstName: '张',
secondName: '三',
})
getName({
firstName: '张',
secondName: '三',
age: 18,
})
函数类型接口
interface encrypt {
(key: string, value: string): string;
}
const md5: encrypt = function(key: string, value: string): string {
return key + value;
};
console.log(md5('name', 'zhangsan'));
const test: encrypt = function(key: string, value: string): string {
return key + '--' + value;
};
console.log(test('name', 'zhangsan'));
可索引接口:数组、对象的约束(不常用)
// 数组约束
interface UserArr {
// 规定数组每一项数据都是 string 类型
[index: number]: string;
}
const arr: UserArr = ['aaa', 'bbb'];
// const arr: UserArr = [123, 'bbb']; // 错误写法
// 对象约束
interface UserObj {
[index: string]: string;
}
const obj: UserObj ={
name: '张三',
};
类类型接口
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 + '吃粮食');
}
}
const d = new Dog('旺财');
d.eat();
接口扩展:接口可以继承接口
interface Animal {
eat(): void;
}
interface Personal extends Animal {
work(): void;
}
class Web implements Personal {
public name: string;
constructor(name: string) {
this.name = name;
}
// 当类所继承的接口继承了其他接口的时候,这个类还必须实现其父级接口的方法
eat() {
console.log(this.name + '吃');
}
work() {
console.log(this.name + '工作');
}
}
const w = new Web('李四');
w.eat();
w.work();
ts中的泛型
作用是校验类型,却不固定类型。一般用于模板通用方法。
泛型函数
简单示例:
function a<T>(value: T): T {
return value;
}
泛型类
// 这里的 T 就是泛型,通过对最外面的 T 的类型的定义,决定了其内部的所有的 T 的类型的定义。
class Min<T> {
public list: T[] = [];
add(value: T): void {
this.list.push(value);
}
min(): T {
let minNum = this.list[0];
for (let i = 0; i < minNum.length; i++) {
if (minNum > this.list[i]) {
minNum = this.list[i];
}
}
return minNum;
}
}
const m1 = new Min<number>();
m1.add(12);
m1.add(3);
m1.add(9);
console.log(m1.min()); // 3
const m2 = new Min<string>();
m2.add('j');
m2.add('v');
m2.add('a');
console.log(m2.min()); // a
泛型接口
第一种写法:
interface ConfigFn {
<T>(value: T): T;
}
const getData: ConfigFn = function<T>(value: T): T {
return value;
}
getData<string>('张三');
第二种写法:
interface ConfigFn<T> {
(value: T): T;
}
function getData<T>(value: T): T {
return value;
}
const myGetData: ConfigFn<string> = getData;
myGetData('20');
装饰器
装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或者参数上,可以修改类的行为。
常见的装饰器有:类装饰器,属性装饰器,方法装饰器,参数装饰器。
类装饰器
普通装饰器
// 装饰器
function logClass(params: any) {
console.log(params); // 打印的就是被装饰的类
params.prototype.apiUrl = '动态扩展的属性';
}
@logClass
class HttpClient {
constructor() {
}
getData() {
}
}
const http: any = new HttpClient();
console.log(http.apiUrl);
装饰器工厂
可以传入参数
function logClass(params: string) {
return function(target: any) {
console.log(target); // HttpClient
console.log(params); // hello
};
}
@logClass('hello')
class HttpClient {
constructor() {
}
getData() {
}
}
属性装饰器
属性装饰器表达式会在运行时当做函数被调用,传入下列两个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名字。
function logProperty(params: any) {
return function(target: any, attr: any) {
console.log(target); // HttpClient
console.log(attr); // 'url'
target[attr] = params; // 修改URL
}
}
class HttpClient {
@logProperty('http://www.baidu.com')
public url : anty | undefined;
constructor() {}
getData() {
console.log(this.url);
}
}
const http = new HttpClient();
http.getData(); // 'http://www.baidu.com'
方法装饰器
它被应用到方法的属性描述符上,可以用来监视,修改或者替换方法定义。方法装饰器会在运行时传入下列三个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名字。
- 成员的属性描述符。
function logMethod(params: any) {
return function (target: any, methodName: any, desc: any) {
console.log(target);
console.log(methodName);
console.log(desc); // getData
// 添加属性和方法
target.apiUrl = 'xxx';
target.run = function() {
console.log('run');
};
// 修改装饰器的方法,把装饰器方法里面传入的所有参数改为 string 类型
// 先将原始方法保留
const oMethod = desc.value;
// 修改方法
desc.value = function (...args: any[]) {
args = args.map(item => {
return String(value);
});
// 对象冒充
// 如果去掉这句话,原始方法就不会执行了,等同于替换了原始方法;加上这句话,会先执行这个被修改的方法,然后运行原始方法
oMethod.apply(this, args);
}
};
}
class HttpClient{
public url: any | undefined;
constructor() {}
@logMethod('http://www.baidu.com')
getData() {
consoe.log(this.url);
}
}
const http: any = new HttpClient();
console.log(http.apiUrl);
http.run();
参数装饰器
参数装饰器表达式会在运行时当做函数调用,可以使用参数装饰器为类的原型增加一些元素数据,传入下列3个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 方法的名字。
- 参数在函数参数列表中的索引。
function logParams(params: any) {
return function (target: any, methodName: any, paramsIndex: any) {
console.log(params); // haha
console.log(target); // HttpClient
console.log(methodName); // getData
console.log(paramsIndex); // 0
targrt.apiUrl = params;
};
}
class HttpClient {
public url: any | undefined;
constructor() {}
getData(@logParams('haha') uuid: any) {
console.log(uuid); // 123456
}
}
const http = new HttpClient();
http.getData(123456);
console.log(http.apiUrl); // haha
装饰器执行顺序
属性 》方法 》方法参数 》类。
如果有多个同样的装饰器,在后面的装饰器会先执行。