TypeScript的核心原则之一是对值所有结构进行类型检查。
function printLabel(labelledObj: { label: string}){
console.log(labelledObj.label);
}
let myObj = { size: 10, label: "size 10 object"};
printLabel(myObj);
下面用接口重写上面的例子:
interface LabelledValue{
label: string;
}
function printLabel(labelledObj: LabelledValue){
console.log(labelledObj.label);
}
可选属性
interface SquareConfig{
color?: string;
width?: number;
}
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.are = config.width * config.width;
}
return newSquare;
}
let mySquare = createSquare({color: "black"});
可选属性的好处是:
- 可以对存在的属性进行预定义;
- 可以捕获引用了不存在的属性时的错误。
只读属性
一些对象属性只能在刚创建的时候修改其值,可以使用readonly来指定只读属性:
interface Point{
readonly x: number;
readonly y: number;
}
可以赋值一个对象字面量构造一个Point。赋值后,x和y就不能再改变。
let p1: Point = {x: 10, y: 20};
p1.x = 5; //error
TypeScript具有ReadonlyArray<T>类型,它与Array<T>相似,只是把所有可变方法去掉了,可以确保数组创建后不能再被修改:
let a: number[] = [1, 2, 3];
let ro: ReadonlyArray<number> = a;
ro[0] = 12; //error
ro.push(5); //error
ro.length = 100; //error
a = ro; //error(这个为什么报错呢?)
上面代码的最后一行,把整个ReadonlyArray赋值到一个普通对象也是不可以的。但可以使用类型断言重写:
a = ro as number[];
判断是使用readonly还是使用const的方法是看把它当做变量使用还是属性使用。如果是变量就用const,如果是当属性使用,就使用readonly。
函数类型
interface SearchFunc{
(source: string, substring: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, substring: string){
let result = source.search(subString);
return result > -1;
}
//对于函数列表,形参不要求一致。重写上面的代码:
let mySearch: SearchFunc;
mySearch = function(src: string, sub: string): boolean{
let result = src.search(sub);
return result > -1;
}
可索引的类型
与使用接口描述函数类型差不多,我们也可以描述那些能够通过索引得到的类型,比如a[10]或ageMap["daniel"]。可索引类型具有一个索引签名,它描述了索引的类型,还有相应的索引返回值类型。
interface StringArray{
[index: number]: string;
}
let myArray: StringArray;
myArray = ["Bob", "Fred"];
let myStr: String = myArray[0];
可以将索引签名设置为只读,这样就防止了给索引赋值:
interface ReadonlyStringArray{
readonly [index: number]: string;
}
let myArray: ReadonlyStringArray = ["Alice", "Bob"];
myArray[2] = "Mallory"; //error
类类型
实现接口
在接口里描述一个方法,在类里实现它,如下setTime方法:
interface ClockInterface{
currentTime: Date;
setTime(d: Date);
}
class Clock implements ClockInterface{
currentTime: Date;
setTime(d: Date){
this.currentTime = d;
}
constructor(h: number, m: number){ }
}
继承接口
和类一样,接口也可以相互继承:
interface Shape{
color: string;
}
interface Square extends Shape{
sideLength: number;
}
let square = <Square>{};
square.color = "blue";
square.sideLength = 10;
一个接口可以继承多个接口,创建出多个接口的合成接口
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;
混合类型
一个对象可以同时作为函数和对象使用,并带有额外的属性。
interface Counter{
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter{
let counter = <Counter>function(start: number){ };
counter.interval = 123;
counter.reset = function(){ };
return counter;
}
let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;