TypeScript 简介
- TypeScript 是微软开发的一款开源编程语言
- TypeScript 是 JavaScript 的超级,遵循 Es6、Es5 规范
TypeScript 使用
- 安装 TypeScript
npm install -g typescript
- 使用
tec命令编译.ts扩展名的文件
tsc test.ts
TypeScript 中的类型注解
- 为了使编写代码规范,利于维护,增加了类型校验
布尔类型(boolean)
let flag: boolean = true;
flag = 123; // 错误
flag = false; // 正确
数字类型(number)
let num: number = 123;
num = "str"; // 错误
num = 456; // 正确
字符串类型(string)
let str: string = "this is ts";
str = true; // 错误
str = "haha"; // 正确
数组类型(array)
let arr: number[] = [11, 22, 33];
let arr2: Array<number> = [11, 22, 33];
let arr3: any[] = ["1314", 22, true];
元组类型(tuple)
- 定长的数组,属于数组的一种
let arr: [number, string] = [123, "this is ts"]; // 定义数组内部的数据类型
枚举类型(enum)
- 处理非数值的数据,尽量用自然语言中含义清楚的单词来表示它的每一个值
enum 枚举名{ 标识符[=整型常数], 标识符[=整型常数], ... 标识符[=整型常数], } ;
enum Flag {success=1,error=2};
let s:Flag=Flag.success;
console.log(s); // 1
任意类型(any)
let oDiv: any = document.getElementById("div");
oDiv.style.color = "red";
null 和 undefined
- 定义没有赋值就是 undefined
let num: number | undefined;
let num: number | null | undefined; // 一个元素可能是 number类型 可能是null 可能是undefined
void 类型
- 表示没有任何类型,一般用于定义方法的时候方法没有返回值。
function run(): void {
console.log("run");
}
run();
never 类型
- 包括 null 和 undefined 的子类型,代表从不会出现的值。
let a:undefined; a=undefined; // a只能等于undefined
let b:null; b=null; // b只能等于null
/ /声明never的变量只能被never类型所赋值
function throwError(msg:string):never{ throw new Error(msg);}
TypeScript 中的函数
function run(): string {
return "run";
}
// ts中定义方法传参
function getInfo(name: string, age: number): string {
return `${name} --- ${age}`;
}
// 没有返回值的方法,使用void类型
function run(): void {
console.log("run");
}
// 可选参数加?
// 注意:可选参数必须配置到参数的最后面
function getInfo(name: string, age?: number): string {
return `${name} --- ${age}`;
}
// 默认参数
function getInfo(name: string, age: number = 20): string {
return `${name} --- ${age}`;
}
// 剩余参数:三点运算符 接受新参传过来的值
function sum(a: number, b: number, ...result: number[]): number {}
sum(1, 2, 3, 4, 5, 6);
// ts函数重载
// java中方法的重载:函数名相同,参数不同。
// typescript中的重载:通过为同一个函数提供多个函数类型定义来试下多种功能的目的。
// es5中出现同名方法,下面的会替换上面的方法
function getInfo(str: any): any {
return typeof str === "string" ? "我叫:" + str : "我的年龄是" + str;
}
TypeScript 中的类
类:图纸(Array、汽车设计图、模子) 实例:产品 (arr、汽车、盆)
ts 中类的定义 class
class Person {
name: string; // 属性 前面省略了public关键词
constructor(n: string) {
//构造器 实例化类的时候触发的方法
this.name = n;
}
run(): void {
//方法 不返回值
alert(this.name);
}
}
let p = new Person("张三");
p.run();
ts 中实现继承 extends
class Web extends Person {
age: number;
constructor(name: string, age: number) {
super(name); // 2、初始化父类的构造函数,把李四传到父类的方法中执行
this.age = age;
}
}
let w = new Web("李四"); // 1、把参数李四传入到Web的constructor中
父类的方法和子类的方法一致,先执行子类的方法,子类重写父类。
ts 三种修饰符
- public:公有 、、 能用
- protected:保护类型 、 能用、 不能用
- private :私有 能用、、 不能用
- readonly :只读 1.初始赋值 2.构造器中初始化修改 其他地方不能改
- static :静态成员 不需要实例化就能用 如:Array.from(), Object.keys(), Math.max()
ts 访问器 get set
class Person{
private _a=0;
public get a(){return this._a;}
public set a(val){
if(val>0){this._a=val;}else{throw new Error('a must be > 0');}
}
}
let p=new Person(); console.log(p.a);
ts 多态
多态:父类定义一个方法不去实现,让继承它的子类去实现 每一个子类有不同的表现
//多态属于继承,代码在运行时具体决定哪个函数
class Animal {
eat() {
console.log("吃的方法");
}
}
class Dog extends Animal {
eat() {
return this.name + "吃粮食";
}
}
class Cat extends Animal {
eat() {
return this.name + "吃猫粮";
}
}
ts 中的抽象类
- 提供其他类继承的基类,不能直接被实例化。就是一个标准,用
abstract关键字定义抽象类和抽象方法,抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。abstract 抽象方法只能放在抽象类里面- 抽象类和抽象方法用来定义标准
abstract class Animal{
abstract eat():any; //抽象方法不包含具体实现必须在派生类中实现。
}
// let a=new Animal() 错误的写法,抽象类不能够被实例
class Dog extends Animal{ // 抽象类的子类必须实现抽象类里面的抽象方法
eat(){console.log(this.name+'吃粮食')}
}
class Cat extends Animal{// 抽象类的子类必须实现抽象类里面的抽象方法
eat(){console.log(this.name+'吃老鼠')}
}
TypeScript 中的接口
- 在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范。不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,只规定这批类里必须提供某些方法,提供这些方法的类就可以满足实际需要。 typescrip 中的接口类似于 java,同时还增加了更灵活的接口类型,包括属性、函数、可索引和类等。
- 接口:行为和动作的规范,对批量方法进行约束
对象接口
interface FullName {
firstName: string; // 注意;结束
secondName: string;
}
function printName(name: FullName) {
// 必须传入对象 firstName secondName
console.log(name.firstName + "--" + name.secondName);
}
// 参数的顺序可以不一样,传入的参数必须包含 firstName secondName
let obj = { age: 20, firstName: "张", secondName: "三" };
printName(obj);
// 可选属性?
interface FullName {
firstName: string;
secondName?: string;
}
函数类型接口
interface encrypt {
(key: string, value: string): string;
}
let md5: encrypt = function (key: string, value: string): string {
return key + value;
};
console.log(md5("name", "zhangsan"));
// 可索引接口 对数组的约束
interface UserArr {
[index: number]: string;
}
let arr: UserArr = ["aaa", "bbb"]; // √
let arr: UserArr = [123, "bbb"]; // 错误
// 可索引接口 对对象的约束
interface UserObj {
[index: string]: string;
}
let arr: UserObj = { name: "张三" };
接口的继承 implements
interface Animal{ //类接口有属性和方法
name:string;
eat(str:string):void;
}
class Dog implements Animal{ // 类集成接口使用implements (实现)
name:string;
constructor(name:string){this.name=name;}
eat(){console.log(this.name+'吃粮食')}
}
// 构造器的interface
interface BoxConstructorInterface{new (a:string);} //构造器接口
interface BoxInterface{show(a:number):void;} //类的接口
const Box:BoxConstructorInterface=class implements BoxInterface {
private a:string;
constructor(a:string){this.a=a;}
show(a:number){alert(this.a+a);}
}
// 接口继承接口:
interface Animal{eat():void;}
interface Person extends Animal{work():void;}
class Web implements Person{
public name:string;
constructor(name:string){this.name=name;}
eat(){console.log(this.name+'喜欢吃馒头')}
work(){console.log(this.name+'写代码');}
}
// 接口继承类:使用这个接口也必须先继承这个类
class Box {private width:number;}
interface BoxInter extends Box{user:string;}
class A extends Box implements BoxInter{user:string;}
TypeScript 中的泛型
- 考虑可重用性,不仅能够支持当前的数据类型,也能支持未来的数据类型。
- 可以支持不特定的数据类型,把类型作为一个特殊的参数传进去
- T 表示泛型,具体什么类型是调用这个方法的时候决定的
function getData<T>(value:T):T{return value;}
getData<number>(123);
getData<string>('1314');
getData<number>('1212'); // 错误
function getData<T>(value:T):any{return '2145214214';}
getData<number>(123); // 参数必须是number
// 类的泛型
class MinClas<T>{
public list:T[]=[];
add(value:T):void{
this.list.push(value);
}
min():T{
let minNum=this.list[0];
for(let i=0;i<this.list.length;i++){
if(minNum>this.list[i]){
minNum=this.list[i];
}
}
return minNum;
}
}
let m1=new MinClas<number>(); //实例化类 并且制定了类的T代表的类型是number
m1.add(11); m1.add(3); m1.add(2); alert(m1.min())
let m2=new MinClas<string>(); //实例化类 并且制定了类的T代表的类型是string
m2.add('c'); m2.add('a'); m2.add('v'); alert(m2.min())
// 1、泛型接口
interface ConfigFn{<T>(value:T):T;}
let getData:ConfigFn=function<T>(value:T):T{
return value;
}
// 2、泛型接口
interface ConfigFn<T>{(value:T):T;}
function getData<T>(value:T):T{ return value;}
let myGetData:ConfigFn<string>=getData;
myGetData('20'); /*正确*/ myGetData(20) //错误
// 3、泛型的extends -- 限定范围
class Box<T extends Date>{
private a:T;
constructor(a:T){this.a=a;}
show(){console.log(this.a);}}
let b=new Box(new Date());
总结
- 定义类型由两种方式:
接口(interface)和类型别名(type alias)interface 只能定义对象类型,type 声明的方式可以定义组合类型,交叉类型和原始类型 1、interface 方式可以实现接口的 extends/implements,而 type 不行 2、interface 可以实现接口的 merge,但是 type 不行 1.type 适合:变量、参数、函数。声明类型 变量、函数 √ class × type Fn=(a:number,b:number)=>number; 2.interface:适合细节:class、constructor 3.abstract:适合主干,定义标准:一对一,层级 4.泛型:比较灵活