概要
TypeScript的核心原则之一是对值所具有的结构进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。 在TypeScript里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。
和JAVA一样通过interface定义,可以用来实现(implements )和继承(extends)
1、简单使用
/**--声明一个接口,这个接口不会在js上面出现,只会在显示一个user对象在getUserInfo*/
interface IUserInfo{
age : any;//定义一个任何变量的age.
userName :string;//定义一个username.
}
/*********获取用户信息*******/
function getUserInfo(user : IUserInfo):string{
return user.age+"======"+user.userName;
}
//用一个数组对象作为一个user对象传值过getUserInfo函数方法..参数必须要以接口IUserInfo对应上.
//少传一个参数,typescript会自动帮你检测报错,如果用纯javascript去写的话,不会报错,ts大大减少检查js问题
//如:var userObj={userName:'周伯通'};//error
var userObj={userName:'周伯通',age:100};
$(function(){
//定义变量接收值..
var userInfo:string= getUserInfo(userObj);
console.log(userInfo);
});
2、可选属性
接口里的属性不全都是必需的。属性名后面加上?表示是一个可选属性。
interface USB{
name?:string;
age?:number;
}
function printUSB(pu:USB){
console.log(pu.name);
console.log(pu.age);
}
var me={name:'jason'};
printUSB(me);
3、只读属性
只读属性用readonly修饰,一旦该属性赋值后,就不能再修改了,否则编译器报错。
前几章中学习了常量const,它们没有什么差别,最简单判断该用readonly还是const的方法是看要把它做为变量使用还是做为一个属性。 做为变量使用的话用 const,若做为属性则使用readonly。
interface Point {
readonly x: number;
readonly y: number;
}
let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error!
4、函数
为了使用接口表示函数类型,我们需要给接口定义一个调用签名。 它就像是一个只有参数列表和返回值类型的函数定义。参数列表里的每个参数都需要名字和类型。
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;
}
函数的参数会逐个进行检查,要求对应位置上的参数类型是兼容的。 如果你不想指定类型,TypeScript的类型系统会推断出参数类型,因为函数直接赋值给了 SearchFunc类型变量。 函数的返回值类型是通过其返回值推断出来的(此例是 false和true)。 如果让这个函数返回数字或字符串,类型检查器会警告我们函数的返回值类型与 SearchFunc接口中的定义不匹配。
let mySearch: SearchFunc;
mySearch = function(src, sub) {
let result = src.search(sub);
return result > -1;
}
5、索引类型
与使用接口描述函数类型差不多,我们也可以描述那些能够“通过索引得到”的类型,比如a[10]或ageMap["daniel"]。 可索引类型具有一个 索引签名,它描述了对象索引的类型,还有相应的索引返回值类型。
interface StringArray{
[index:number]:string;
}
var myArray:StringArray=['jason','john'];
console.log(myArray);
上面例子里,我们定义了StringArray接口,它具有索引签名。 这个索引签名表示了当用 number去索引StringArray时会得到string类型的返回值。
共有支持两种索引签名:字符串和数字。 可以同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型。 这是因为当使用 number来索引时,JavaScript会将它转换成string然后再去索引对象。 也就是说用 100(一个number)去索引等同于使用"100"(一个string)去索引,因此两者需要保持一致。
上面例子里,我们定义了StringArray接口,它具有索引签名。 这个索引签名表示了当用 number去索引StringArray时会得到string类型的返回值。
class Animal {
name: string;
}
class Dog extends Animal {
breed: string;
}
// 错误:使用'string'索引,有时会得到Animal!
interface NotOkay {
[x: number]: Animal;
[x: string]: Dog;
}
字符串索引签名能够很好的描述dictionary模式,并且它们也会确保所有属性与其返回值类型相匹配。 因为字符串索引声明了 obj.property和obj["property"]两种形式都可以。 下面的例子里, name的类型与字符串索引类型不匹配,所以类型检查器给出一个错误提示:
interface NumberDictionary {
[index: string]: number;
length: number; // 可以,length是number类型
name: string // 错误,`name`的类型与索引类型返回值的类型不匹配
}
最后,你可以将索引签名设置为只读,这样就防止了给索引赋值:
interface ReadonlyStringArray {
readonly [index: number]: string;
}
let myArray: ReadonlyStringArray = ["Alice", "Bob"];
myArray[2] = "Mallory"; // error!
6、接口实现和继承
实现:
interface ReadonlyStringArray {
readonly [index: number]: string;
}
let myArray: ReadonlyStringArray = ["Alice", "Bob"];
myArray[2] = "Mallory"; // error!
继承: