主要知识点:接口、类、函数、泛型
1.接口
介绍:typescript核心原则之一是对值所具有的结构进行类型检查,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约(相当于MVC模式中的model,用来定义数据模型)
例子: interface People{
name: string;
}
function printNmae (people :Pelple){
Console.log(people.name);
}
let my = { name:”张三”,age:9};
printName(my );
People接口相当与是一个模型,代表了一个name属性且类型为string的对象。只要传入的数据满足这个接口中的条件,不在乎属性个数和顺序(只存在与函数传参中)
1.1可选属性 ?:
代表这个接口类型,可以不包含这个属性
例子:interface People{
name ?: string;
age ?: number;
}
let people : People = {name:”张三”}; ------这里没有Age属性,不会报错
1.2只读属性 readonly
例子:interface People{
readonly name : string;
readonly age : number;
}
let people : People = {name:”张三”,age:6}; ------第一次赋值后,name和age都不能变了
1.3额外的属性检查
对象字面量会被特殊对待会经过 额外属性检查,当将它们赋值给变量或作为参数传递的时候。 如果一个对象字面量存在任何“目标类型”不包含的属性时,你会得到一个错误。
例子:
let people : People = {name:”张三”,age:6,a:9787}; -------赋值给变量时,People接口不属性a,因此会报错
解决方式1: 使用类型断言as
解决方式2:接口添加属性[propName: string]: any;,表示可以有任意数量的属性,并且只要不是name或age
interface People{
readonly name : string;
readonly age : number;
[propName: string]: any;
}
1.4函数类型接口
接口内部定义一个函数签名:相当于定义一个java中的抽象方法,只有参数和返回值类型,没有方法体。
例子:interface Func{
(prop:string):number;
}
let func:Func;
func = function(p:string){ ----------参数名不一定与接口定义的名字一致
return 5;
}
1.5可索引类型接口(相当于数组类型)
接口内部定义一个索引签名
例子:interface array{
[index:number]:string; ----签名表示用number类型去索引array会得到string类型的返回值
}
let myArray: array;
myArray = ["Bob", "Fred"];
let myStr: string = myArray[0]; --------myStr = “Bob”
1.6类类型接口
实现接口:与java里的接口基本作用一样,限制类去符合接口的类型。
例子:
interface ClockInterface {
currentTime: Date;
setTime(d: Date);
}
class Clock implements ClockInterface {
currentTime: Date;
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) { }
}
1.7继承接口
接口相互继承,我们能从一个接口中复制成员到另一个接口。并且可以继承多个接口。
例子:
interface Shape {
color: string;
}
interface PenStroke {
penWidth: number;
}
interface Square extends Shape, PenStroke {
sideLength: number;
}
let square = <Square>{};
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;
2.类
从es2015后,支持我们使用基于类的继承并且对象是由类构建出来的。
2.1类
例子:
class People{
name:string;
age:number;
constructor(name:string,age:number){
this.name = name ;
this.ahe = age;
}
say(){
Console.log(“我具有说话的功能”);
}
}
let xx = new People(“张三”,18);
这个类有4个成员:一个叫做name和age的属性,一个构造函数和一个 say方法。
2.2继承
子类会从继承的基类中继承属性和方法。并且子类的构造函数必须用super()调用父类的构造函数。并且允许对象是父类的类型,子类的形态。调用的也是子类的方法。
例子:老师类继承上面的人类。
class Teacher extend People{
subject:string;
constructor(name:string,age:number,subject:string){
super(name ,age); //调用父类构造函数
this.subject= subject;
}
gotoclass(){
Console.log(“我要去上课啦”);
}
}
let tea = new Teacher(“李四”,25,”语文课”);
let tea:People = new Teacher(“李四”,25,”语文课”); //父类类型,子类形态
2.3公有的,私有的,受保护的修饰符
默认公有 public:typescript中不声明则是public,所有地方都有权利访问public定义的属性或方法。
私有的private:只有类内部可以访问。
受保护的protected:类内部包括派生类中的方法可以访问
readonly name:string;
readonly修饰符,将属性设置为只读,必须在声明时或构造函数内可以被初始化。
参数属性:
创建和初始化 name成员。 我们把声明和赋值合并至一处。使用访问修饰符定义参数属性,相当于定义成员的访问修饰。
class People{
constructor(private name:string){}
}
相当于:
class People{
private name:string;
constructor(name:string){
this.name = name;
}
}
2.4存取器
通过getters/setters来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问。
例子:
class People{
_name:string;
set name(val:string){
//可以对设置的参数进行格式化,或验证等等。
this._name = name.trim();
}
get name():string{
return this._name;
}
}
2.5静态属性
之前谈论的都是类的实例成员,那些只有当类被实例化时才会被初始化的属性值。我们可以用static创建类的静态属性,访问静态属性不在是this.属性名,应该是类名.属性名。
2.6抽象类
抽象类做为其它派生类的基类使用。 它们一般不能直接被实例化。 不同于接口,抽象类可以包含成员的实现细节(即非抽象方法)。abstract关键字是用于定义抽象类和在抽象类内部定义抽象方法。派生类继承抽象类必须实现抽象类中的抽象方法
3.函数
函数是JavaScript应用程序的基础。 它帮助你实现抽象层,模拟类,信息隐藏和模块。 TypeScript为JavaScript函数添加了额外的功能,让我们可以更容易地使用。
3.1函数
javascript中有名字函数和匿名函数
function add(a,b){
return a+b;
}
let add = function(a,b){
return a+b;
}
3.2函数类型
为函数定义类型:函数参数类型以及返回值
function add(a:number,b:number):number{
return a+b;
}
书写完整函数定义类型:函数参数类型以及返回值,变量为函数类型,函数里的参数,可以与变量得函数类型参数不一样
let add: (a:number,b:number) => number = function(a:number,b:number):number{
return a+b;
}
3.3可选参数和默认值
可选参数
JavaScript里,每个参数都是可选的,可传可不传。 没传参的时候,它的值就是undefined。 在TypeScript里我们可以在参数名旁使用 ?实现可选参数的功能。 比如,我们想让last name是可选的:
例子:function buildName(firstName: string, lastName?: string) {
if (lastName)
return firstName + " " + lastName;
else
return firstName;
} ------------可选参数需放在必选参数后面
默认值
在TypeScript里,我们也可以为参数提供一个默认值当用户没有传递这个参数或传递的值是undefined时。 它们叫做有默认初始化值的参数。 让我们修改上例,把last name的默认值设置为"Smith"。
例子:function buildName(firstName: string, lastName = “aaa”) {
if (lastName)
return firstName + " " + lastName;
else
return firstName;
} ------------默认值参数可以放在必须参数前,调用时想使用默 认值时传undefined,否则传的参数必须与默认值参数类型一致。
3.4剩余参数
有时,你想同时操作多个参数,或者你并不知道会有多少参数传递进来。 在JavaScript里,你可以使用 arguments来访问所有传入的参数。
在TypeScript里,你可以把所有参数收集到一个变量里:
例子:
function buildName(firstName: string, ...restOfName: string[]) {
return firstName + " " + restOfName.join(" ");
}
let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
4.泛型
定义:软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
在像C#和Java这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。
4.1泛型定义
泛型函数:
function fn<T>(x:T):T{
return x;
}
使用:
fn<string>(“asd”);
或者
fn(“asd”);(类型推论,根据传入的参数判断T为string类型)
4.2使用泛型变量
使用泛型创建像identity这样的泛型函数时,编译器要求你在函数体必须正确的使用这个通用的类型。 换句话说,你必须把这些参数当做是任意或所有类型。
例子:
function loggingIdentity<T>(arg: T): T {
//这样会报错,因为arg,代表所有类型,而并不是所有类型都有length属性
console.log(arg.length); // Error: T doesn't have .length return arg;
}
解决办法:将泛型变量变成类型的一部分,如 prop:T[]
例子:
function loggingIdentity<T>(arg: T[]): T[] {
//这样会成功,因为arg代表元素类型T的数组
console.log(arg.length);
return arg;
}
4.3泛型类型
例子:
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: <T>(arg: T) => T = identity; ----------函数参数前多一个类型参数<T>
使用对象字面量或泛型接口定义泛型函数;
例子:
let myIdentity: { <T>(arg: T) } => T = identity; ---------对象字面量
Interface x{
<T>(arg:T):T;
}
let myIdentity: x=> T = identity; ---------泛型接口
还可以把泛型参数作为接口的一个参数
例子:
Interface x<T>{
(arg:T):T;
}
let myIdentity: x<number>=> T = identity; ---------泛型接口
4.4泛型类
例子:
class GenericNumber<T> {
zeroValue: T; add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
4.5泛型约束<T extends type>
约束泛型是那些类型
例子:
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); ----------泛型继承了接口Lengthwise ,所有必须存 在length属性,在这里不会报错
}
调用:loggingIdentity({length:3,a:”asdas”});