interface 基本
是什么?
- 用户自定义的类型,定义基本类型中不存在类型
- 相当于c++ 的结构体 struct (个人理解)
作用
描述普通对象
- 固定属性名和类型,用于类型检查 例子1,2,3
- 定义变量比接口少了一些属性是不允许的
- 多一些属性也是不允许的
描述函数类型
- 固定输入:输出类型,相当于把函数的框架搭建好,例子4
描述索引类型
- 固定object/array的索引类型,索引是指objec.key或者array.index,例子5
语法 接口一般首字母大写。 有的编程语言中会建议接口的名称加上 I 前缀
例子1 属性检查
// interface定义
interface Person { firstName: string; lastName: string}
// interface使用: 函数形参
function greeter(p: Person){
return `${p.firstName} ${p.lastName}`
}
// 隐式类型检查
let intUser1 = {firstName: 'san', lastName: 'zhang'}; // ok
console.log("intUser1: ", greeter(intUser1)); // intUser1: san zhang
// 显式类型检查
let intUser2: Person = {firstName: 'san', lastName: 'zhang'}; // ok
console.log("intUser2: ", greeter(intUser2)); // intUser2: san zhang
/*
多的属性 nickName
*/
let initUser31 = {firstName: 'san', lastName: 'zhang', nickName: 'xiaozhang'}; // ok
console.log("initUser31: ", greeter(initUser31)); // initUser31: san zhang
// let initUser32:Person = {firstName: 'san', lastName: 'zhang', nickName: 'xiaozhang'}; // compile error!
// console.log("initUser32: ", greeter(initUser32));
console.log("initUser fun: ", greeter({firstName: 'san', lastName: 'zhang', nickName: 'xiaozhang'} as Person)); // ok initUser fun: san zhang
检查分类
- 隐式类型检查
- 显式类型检查
检查变量
- 检查存在:属性是不是都有?
- 检查类型:类型是不是正确?
- 不检查顺序:属性顺序可以随意
- 不检查多余:变量多余属性没关系(显示类型除外)
例子2 可选属性
interface SquareConfig { color?: string, width?: number }
// config表示参数类型, color/area表示返回值类型
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;
}
console.log('newSquare: ', newSquare);
return newSquare;
}
createSquare({}); // { color: 'white', area: 100 }
createSquare({color: 'black'}); // { color: 'black', area: 100 }
createSquare({width: 5}); // { color: 'white', area: 25 }
createSquare({color: 'red', width: 1}); // { color: 'red', area: 1 }
// 使用类型断言(类型转化)可以解决多余属性的检查
createSquare({color: 'red', opactiy: 0.5} as SquareConfig); // { color: 'red', area: 100 }
可选属性是什么?
属性名称后接问号
可选属性作用? 对可能属性进行预定义;
例子3 只读属性
// 只读属性
interface Point { readonly x: number; readonly y: number }
let p1: Point = {x: 1, y:2}
console.log(p1.x, p1.y); //ok 1 2
// p1.x = 3; // error: Cannot assign to 'x' because it is a read-only property.
// 只读数组
let intArr2: ReadonlyArray<number> = [4,5,6];
console.log(intArr2); // [ 4, 5, 6 ]
// intArr2[0] = 400; // error:Index signature in type 'readonly number[]' only permits reading.
只读属性的定义?
通过readonly, ReadonlyArray
只读属性的作用?
只有第一次初始化时可以被赋值,
之后只能读,不能写了
例子4 函数接口
interface searchFun {
(source: string, subString: string) : boolean
}
let mySearchFun: searchFun = function(src: string, sub:string): boolean{
let result = src.search(sub);
return result > -1;
}
console.log(mySearchFun('abc123abc', '123')); // true
console.log(mySearchFun('abc123abc', '1234')); // false
语法
(参数1,参数2) : 返回值
作用
描述函数
例子5 索引签名
/*
索引签名为number
*/
// 描述key为number,value为number的对象 (=>数组)
interface Grades {
[x: number]: number
};
let myGrade: Grades = [90,95,100];
let grade0: number = myGrade[0]
console.log(`grade0=${grade0}`); // grade0=90
/*
索引签名为string
*/
// 描述key为string,value为number的对象 (=>普通对象)
interface NameGrades {
[y: string]: number
};
let myNameGrades: NameGrades = {'lily': 80, 'lucy': 90, 'Jonny': 100};
let lucyGrades: number = myNameGrades['Jonny'];
console.log(`lucyGrades=${lucyGrades}`); // lucyGrades=100
/*
索引签名为number+string
*/
// 描述key为string或者number,value为string的对象 (=>普通对象)
interface Okay {
[x: number]: string;
[x: string]: string;
}
let myOkay: Okay = {'name': 'micky', 10: 'haha'};
let okRet1: string = myOkay['name']; // okRet1=micky
let okRet2: string = myOkay[10]; // okRet2=haha
// 注意:如果2个的返回值类型不同时,编译报错
// Numeric index type 'number' is not assignable to string index type 'string'.
// interface NotOkay {
// [x: number]: number;
// [x: string]: string;
// }
/*
索引签名包含index+length
*/
interface nameDictionary {
[index: number]: number,
length: number, // ok length属于字符串索引
}
let myNameDictionary: nameDictionary = [1,2,3];
console.log(`myNameDictionary=${myNameDictionary}`); // myNameDictionary=1,2,3
/*
索引签名可以设置为只读
*/
interface ReadonlyStringArray {
readonly [index: number]: string;
}
let myReadonlyStringArray: ReadonlyStringArray = ['Alice', 'Bob'];
// myReadonlyStringArray=Alice,Bob
console.log(`myReadonlyStringArray=${myReadonlyStringArray}`);
索引签名是什么?
索引下标: objec.key或者array.index
支持两种索引签名
- 字符串
- 2数
例子6 接口的混合类型
接口描述的函数,还可以附加属性和其它方法
interface Counter {
(start: number): string; // 函数描述,接口的本质
interval: number; // 函数包含interval属性
reset(): void; // 函数包含reset方法
}
function getCounter(): Counter {
// 函数描述的实现
let counterStart = function (start:number) {
console.log(`start ${start}`);
}
// 返回值
let counter = <Counter> counterStart;
// 函数属性的描述
counter.interval = 123;
// 函数方法的描述
counter.reset = function() {
console.log('reset!');
}
return counter;
}
let myCount1 = getCounter();
// { [Function: counterStart] interval: 123, reset: [Function] }
console.log(myCount1);
// 调用函数
myCount1(10); // start 10
// 调用函数的reset方法
myCount1.reset(); // reset!
// 赋值函数的interval属性
myCount1.interval = 5.0;