构造函数
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
let greeter: Greeter;
greeter = new Greeter("world");
console.log(greeter.greet());
readonly修饰符
你可以使用readonly
关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化。
class Octopus { readonly name: string; readonly numberOfLegs: number = 8; constructor (theName: string) { this.name = theName; } } let dad = new Octopus("Man with the 8 strong legs"); dad.name = "Man with the 3-piece suit"; // 错误! name 是只读的.
参数属性
在上面的例子中,我们不得不定义一个受保护的成员name
和一个构造函数参数theName
在Person
类里,并且立刻给name
和theName
赋值。 这种情况经常会遇到。参数属性可以方便地让我们在一个地方定义并初始化一个成员。 下面的例子是对之前Animal
类的修改版,使用了参数属性:
class Animal { constructor(private name: string) { } move(distanceInMeters: number) { console.log(`${this.name} moved ${distanceInMeters}m.`); } }
注意看我们是如何舍弃了theName
,仅在构造函数里使用private name: string
参数来创建和初始化name
成员。 我们把声明和赋值合并至一处。
参数属性通过给构造函数参数添加一个访问限定符来声明。 使用private
限定一个参数属性会声明并初始化一个私有成员;对于public
和protected
来说也是一样。
函数
1. 函数类型
function add(x: number, y: number): number { return x + y; }
let myAdd = function(x: number, y: number): number { return x + y; };
完整写法
let myAdd: (x: number, y: number) => number = function(x: number, y: number): number { return x + y; };
第二部分是返回值类型。 对于返回值,我们在函数和返回值类型之前使用( =>)符号,使之清晰明了。 如之前提到的,返回值类型是函数类型的必要部分,如果函数没有返回任何值,你也必须指定返回值类型为 void而不能留空
剩余参数
function buildName(firstName: string, ...restOfName: string[]) { return firstName + " " + restOfName.join(" "); } let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie"); function buildName(firstName: string, ...restOfName: string[]) { return firstName + " " + restOfName.join(" "); } let buildNameFun: (fname: string, ...rest: string[]) => string = buildName;
泛型
1. 初识
function identity<T>(arg: T): T { return arg; }
我们给identity添加了类型变量T。 T帮助我们捕获用户传入的类型(比如:number),之后我们就可以使用这个类型。 之后我们再次使用了 T当做返回值类型。现在我们可以知道参数类型与返回值类型是相同的了。 这允许我们跟踪函数里使用的类型的信息。
我们把这个版本的identity函数叫做泛型,因为它可以适用于多个类型。 不同于使用 any,它不会丢失信息,像第一个例子那像保持准确性,传入数值类型并返回数值类型。
我们定义了泛型函数后,可以用两种方法使用。
第一种是,传入所有的参数,包含类型参数。
let output = identity<string>("myString"); // type of output will be 'string'
这里我们明确的指定了T是string类型,并做为一个参数传给函数,使用了<>括起来而不是()。
第二种方法更普遍。利用了类型推论 -- 即编译器会根据传入的参数自动地帮助我们确定T的类型
let output = identity("myString"); // type of output will be 'string'
function loggingIdentity<T>(arg: T[]): T[] { console.log(arg.length); // Array has a .length, so no more error return arg; } // 或 function loggingIdentity2<T>(arg: Array<T>): Array<T> { console.log(arg.length); // Array has a .length, so no more error return arg; }
泛型类型:
function identity<T>(arg: T): T { return arg; } let myIdentity: <T>(arg: T) => T = identity; // 或 function identity<T>(arg: T): T { return arg; } let myIdentity: <U>(arg: U) => U = identity; // 或 function identity<T>(arg: T): T { return arg; } let myIdentity: {<T>(arg: T): T} = identity;
泛型类:
class GenericNumber<T> { zeroValue: T; add: (x: T, y: T) => T; } let myGenericNumber = new GenericNumber<number>(); myGenericNumber.zeroValue = 0; myGenericNumber.add = function(x, y) { return x + y; };
继承接口
//8. 继承接口 interface Shape { color: string; } interface Square extends Shape { sideLength: number; } let square = <Square>{}; square.color = "blue"; square.sideLength = 10;
interface SquareConfig { color?: string; width?: number; [propName: string]: any; } function createSquare(config: SquareConfig): {color: string; area: number} { let newSquare = {color: "white", area: 100}; if (config.color) { newSquare.color = config.color; } if (config.width) { newSquare.area = config.width * config.width; } return newSquare; } let mySquare = createSquare({color: "black"}); interface StringArray{ [index: number]:string; } let myArray:StringArray; myArray = ["Bob", "fred"]; let myStr:string = myArray[0]; let myArray2:Array<string> = ["Bob2", "Fred2"]; let myStr2 = myArray2[0];