TypeScript语法 中级篇
来源:互联网 发布:java构造器使用实例 编辑:程序博客网 时间:2024/05/23 17:14
泛型
下面来创建第一个使用泛型的例子:identity函数。 这个函数会返回任何传入它的值。
不用泛型的话,这个函数可能是下面这样:
function identity(arg: number): number { return arg;}
或者,我们使用any类型来定义函数:
function identity(arg: any): any { return arg;}
虽然使用any类型后这个函数已经能接收任何类型的arg参数,但是却丢失了一些信息:传入的类型与返回的类型应该是相同的。 如果我们传入一个数字,我们只知道任何类型的值都有可能被返回。
因此,我们需要一种方法使返回值的类型与传入参数的类型是相同的。 这里,我们使用了 类型变量,它是一种特殊的变量,只用于表示类型而不是值。
function identity<T>(arg: T): T { return arg;}
看似与泛型方法类似,但是还是有区别的。比如如下例子:
// 方法一:带有any参数的方法 function any_func(arg: any): any { console.log(arg.length); return arg; } // 方法二:Array泛型方法 function array_func<T>(arg: Array<T>): Array<T> { console.log(arg.length); // Error: T doesn't have .length return arg; }
联合类型
偶尔你会遇到这种情况,一个代码库希望传入 number或string类型的参数。 例如下面的函数:
function padLeft(value: string, padding: any) { if (typeof padding === "number") { return Array(padding + 1).join(" ") + value; } if (typeof padding === "string") { return padding + value; } throw new Error(`Expected string or number, got '${padding}'.`);}padLeft("Hello world", 4); // returns " Hello world"let indentedString = padLeft("Hello world", true); // 编译阶段通过,运行时报错
function padLeft(value: string, padding: string | number) { // ...}let indentedString = padLeft("Hello world", true); // errors during compilation
高级类型
交叉类型(Intersection Types)
交叉类型是将多个类型合并为一个类型。 这让我们可以把现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性。 例如, Person & Serializable & Loggable同时是Person和Serializable和Loggable。 就是说这个类型的对象同时拥有了这三种类型的成员。
我们大多是在混入(mixins)或其它不适合典型面向对象模型的地方看到交叉类型的使用。 (在JavaScript里发生这种情况的场合很多!) 下面是如何创建混入的一个简单例子:
function extend<T, U>(first: T, second: U): T & U { let result = <T & U>{}; for (let id in first) { (<any>result)[id] = (<any>first)[id]; } for (let id in second) { if (!result.hasOwnProperty(id)) { (<any>result)[id] = (<any>second)[id]; } } return result;}class Person { constructor(public name: string) { }}interface Loggable { log(): void;}class ConsoleLogger implements Loggable { log() { // ... }}var jim = extend(new Person("Jim"), new ConsoleLogger());var n = jim.name;jim.log();
构造函数+static
class Greeter { static standardGreeting = "Hello, there"; greeting: string; greet() { if (this.greeting) { return "Hello, " + this.greeting; } else { return Greeter.standardGreeting; } }}let greeter1: Greeter;greeter1 = new Greeter();console.log(greeter1.greet());let greeterMaker: typeof Greeter = Greeter;greeterMaker.standardGreeting = "Hey there!";let greeter2: Greeter = new greeterMaker();console.log(greeter2.greet());
抽象类
我们可以构造出一个固定的一组行为的抽象描述,但是这组行为却能够有任意个可能的具体实现方式。这个抽象描述就是抽象类。
抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。 不同于接口,抽象类可以包含成员的实现细节。 abstract关键字是用于定义抽象类和在抽象类内部定义抽象方法。
abstract class Animal { abstract makeSound(): void; move(): void { console.log('roaming the earch...'); }}
抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。 抽象方法的语法与接口方法相似。 两者都是定义方法签名但不包含方法体。 然而,抽象方法必须包含 abstract关键字并且可以包含访问修饰符。
abstract class Department { constructor(public name: string) { } printName(): void { console.log('Department name: ' + this.name); } abstract printMeeting(): void; // 必须在派生类中实现}class AccountingDepartment extends Department { constructor() { super('Accounting and Auditing'); // constructors in derived classes must call super() } printMeeting(): void { console.log('The Accounting Department meets each Monday at 10am.'); } generateReports(): void { console.log('Generating accounting reports...'); }}let department: Department; // ok to create a reference to an abstract typedepartment = new Department(); // error: cannot create an instance of an abstract classdepartment = new AccountingDepartment(); // ok to create and assign a non-abstract subclassdepartment.printName();department.printMeeting();department.generateReports(); // error: method doesn't exist on declared abstract type
抽象类与接口的区别
1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
2、抽象类要被子类继承,接口要被类实现。
3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现
4、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。
5、抽象方法只能申明,不能实现
6、抽象类里可以没有抽象方法
7、如果一个类里有抽象方法,那么这个类只能是抽象类
8、抽象方法要被实现,所以不能是静态的,也不能是私有的。
9、接口可继承接口,并可多继承接口,但类只能单根继承。
总结:
1.抽象类 和 接口 都是用来抽象具体对象的. 但是接口的抽象级别最高
2.抽象类可以有具体的方法 和属性, 接口只能有抽象方法和不可变常量
3.抽象类主要用来抽象类别,接口主要用来抽象功能.
4、抽象类中,且不包含任何实现,派生类必须覆盖它们。接口中所有方法都必须是未实现的。
- TypeScript语法 中级篇
- TypeScript入门-语法篇
- TypeScript 语法
- TypeScript 基本语法
- [TypeScript语法2]basicTypes
- [typeScript语法3]interface
- [typeScript语法4]class
- [typeScript语法5]functions
- 浅谈TypeScript语法
- [TypeScript语法6]type
- [TypeScript语法7]decorators
- TypeScript 基本语法
- TypeScript 基本语法
- 中级SQL 语法笔记
- [TypeScript语法1]quick start
- [人工智能]人工智能知识体系(语法篇,中级篇,高级篇)
- 中级菜鸟--SQL语法大全
- vim安装Typescript语法高亮
- 解决Navicat 出错:1130-host . is not allowed to connect to this MySql server
- Linux tree命令
- 使用Tomcat j_security_check实现用户登录、注销功能
- ajax在spring环境下,从前端jsp页面传送页面提交值到后端controller
- JavaScript学习指南之第一章Hello JavaScript!最基础的JavaScript入门
- TypeScript语法 中级篇
- 重写hashcode的原因 以及为啥用31的个人理解
- IOS应用内存释放机制
- 【转】gc日志分析工具
- Jmeter3.0发布,版本更新都更新了什么
- Linux下history命令用法
- 用Fiddler模拟低速网络环境
- jstack+top定位性能问题
- CentOS6.7搭建LNMP环境