当前位置:网站首页>layaBox---TypeScript---接口
layaBox---TypeScript---接口
2022-07-30 17:38:00 【格拉格拉】
目录
1.接口示例
TypeScript核心原则之一是对值所具有的结构进行类型检查。被称作“鸭式辫型法”或“结构性子类型化”。
function printLable( lableObj: { lable:string} )
{
console.log( lableObj.lable );
}
let myObj = { size:10, lable:"Size 10 object" };
printLable( myObj );
接口示例:
interface LableValue{
lable: string;
}
function printLable( lableObj: LableValue )
{
console.log( lableObj.lable );
}
let myObj = { size:10,lable:"size 10 object"};
printLable( myObj );
️注意:类型检查器不会去检查属性的顺序,只要相应的属性存在并且类型也是对的就可以。
2.可选属性
接口里的属性不全是必须的,有些只在某些条件下存在,或者根本不存在。
带有可选属性的接口与普通接口的定义差不多,只是在可选属性名字定义后加一个?符号。
好处:
1。可以对可能存在的属性进行预定义。
2. 可以捕获引用了不存在的属性时的错误。
例:
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.area = config.width * config.width;
}
return new Square;
}
let mySquare = createSquare({color:"black"});
3.只读属性
接口:
//一些对象属性只能在对象刚创建的时候修改其值,可以在属性名前 用 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>类型,确保数组创建后再也不能被修改。
let a:number[] = [1,2,3,4];
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
4.额外的属性检查
我们在第一个例子里使用了接口,TypeScript让我们传入{size: number; lable: string}到仅期望得到{lable: string;} 的函数里。 我们也学过了可选属性。
然而,当你天真的将这两者结合的话就会像javaScript里那样搬起石头砸自己的脚。
//拿createSquare例子来说
interface SquareConfig{
color?: string;
width?: number;
}
function createSquare( config: SquareConfig ):{color: string, area: number}
{
//...
}
let mySquare = createSquare( {coor:"red", width: 100} );
注意️:这里传的是coor 而不是 color, 在js中这会默默的失败。然而ts会认为这段代码可能存在bug.
对象字面量会被特殊对待 且 会经过额外属性检查,当它们赋值给变量或作为参数传递时,如果一个对象字面量存在任何‘目标类型’不包含的属性时,你会得到一个Error
//error: 'coor' not expected in type 'SquareConfig'
let mySquare = createSquare( {coor: "red", width: 100} );
想要绕开这些检查非常简单,最简单的方式就是使用类型断言:
let mySquare = createSquare( {width:100, opacity:0.5} as SquareConfig );
然而最佳的避开方式是添加一个字符串索引签名,前提是你能够确定这个对象具有某些作为特殊用途的额外属性。
//如果SquareConfig带有上面定义的类型的color和width属性,并且还会带有任意数量的其它属性,那么我们可以这样定义它:
inteface SquareConfig{
color?: string;
width?: number;
[propName: string]: any;
}
这样SquareConfig就可以带有任意数量的属性,并且只要它们不是color和width ,那么就无所谓它们的类型是什么。
还有一种可以避开额外属性检查的方式:将这个对象赋值给另一个变量。
let squareOption = { coor:"red", width:100 };
let mySquare = createSquare(squareOption);
5.函数类
接口可以描述函数类型
为了使用接口表示函数类型,我们需要给接口定义一个调用签名。参数列表里的每个参数都需要名字和类型
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)
{
let result = src.search(sub);
return result > -1;
}
函数的参数会逐个进行检查,要求对应位置上的参数类型上兼容的。如果你不想指定类型,TS的类型系统会根据返回值推断出参数类型。
6.可索引的类型
与使用接口描述函数类型差不多,我们也可以描述那些能够“通过索引得到”的类型,比如a[10]或ageMap["daniel"].
//可索引类型具有一个 索引签名, 它描述了对象索引的类型。还有相应的索引返回值类型
interface StringArray
{
[index:number]: string
}
let myArray: StringArray;
myArray = ["Bob","Fred"];
let myStr: string = myArray[0];
这里,我们定义了StringArray接口,它具有索引签名。
这个索引签名表示了当用 number去索引StringArray时会得到string类型的返回值
ts支持2种索引签名:字符串 和 数字。
可以同时使用2种类型的索引,但是数字索引的返回值必须是字符串索引返回值的子类型。
这是因为当使用number来索引时,js会将它转换成string 然后再去索引对象。
也就是说用 数字100 去索引 等同于用 字符串“100”去索引,因此两者要保持一致。
//将索引签名设置为只读,这样就可以防止了给索引赋值:
interface ReadonlyStringArray
{
readonly [index:number]:string;
}
let myArray:ReadonlyStringArray = ["Alice","Bob"];
myArray[2] = "Mallory"; //error. 因为索引签名上只读的,所以不能设置
7.类类型
7.1.实现接口
//1.与C#或java里的接口一样,ts也能用它来明确的强制一个类去符合某种契约。
interface ClockInterface{
currentTime: Date;
}
class Clock implements ClockInterface{
currentTime: Date;
constructor(h: number, m: number)
{
}
}
//2.也可以在接口中描述一个方法,在类里实现它。
interface ClockInterface{
currentTime: Date;
setTime(d: Date);
}
class Clock implements ClockInterface
{
currentTime: Date;
setTime(d: Date)
{
this.currentTime = d;
}
constructor(h:number, m:number){}
}
7.2类静态部分与实例部分的区别
类具有2个类型: 静态部分的类型 和 实例的类型。
当一个类实现了一个接口时,只对其实例部分进行类型检查。
因此我们应该直接操作类的静态部分,
例:
interface ClockConstructor
{
new (hour:number, minute:number): ClockInterface;
}
interface ClockInterface
{
tick();
}
function createClock(ctor:ClockConstructor, h: number, m: number ):ClockInterface
{
rerurn new ctor(h, m);
}
class DigitalClock implements ClockInterface
{
constructor(h:number, m: number){}
tick(){
console.log("beep beep");
}
}
let digital = createClock(DigitalClock,7,32);
8.继承接口
//和类一样,接口也可以相互继承。
interface Shape{
color: string;
}
interface Square extends Shape{
sideLength: number;
}
let square = <Square>{};
square.color = "red";
square.sideLength = 10;
//一个接口也可以继承多个接口,创建出多个接口的合成接口。
interface Shape{
color: string;
}
interface PenStroke{
penWidth: number;
}
interface Square extends Shape,PenStroke{
sideLength: number;
}
let squ = <Square>{};
squ.color = "blue";
squ.penWidtg = 5.0;
squ.sideLength = 10;
9.混合类型
例: 一个对象可以同时作为函数和对象使用,并带有额外的属性。
interface Counter{
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter
{
let cter = <Counter> function( start: number ){};
cter.interval = 125;
cter.reset = function(){};
return cter;
}
let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;
在使用js第三方库时,你可能需要像上面这样去完整的定义类型
10.接口继承类
当接口继承了一个类类型时,它会继承类的成员但不包括其实现。
接口同样会继承到类的private和protected成员。 也就意味着,当你创建了一个接口继承了一个拥有私有或保护的成员的类时,这个接口类型只能被这个类或其子类所实现(implement)
//类
class Control
{
private state: any;
}
//接口继承类
interface SelectableControl extends Control
{
select(): void;
}
//类继承类 再实现接口
class Button extends Control implements SelectableControl
{
select(){}
}
//类继承类
class TextBox extends Control
{
select(){}
}
//error "Image"类型缺少“state”属性
class Image implements SelectableControl
{
select(){}
}
上面的例子中 selectableControl 包含了Control的所有成员,包括私有成员 state。
因为state是私有成员,所以只有Control的子类才能实现SelectableControl接口。
边栏推荐
- CMake库搜索函数居然不搜索LD_LIBRARY_PATH
- 顺通海关查验预约综合管理系统
- FastJson反序列化漏洞(复现)
- JMeter Notes 4 | JMeter Interface Introduction
- 基于亚马逊云科技无服务器服务快速搭建电商平台——性能篇
- Promise entry to proficient (1.5w word detailed explanation)
- Test the.net text to Speech module System. Researched
- 信息学奥赛一本通 1915:【01NOIP普及组】最大公约数与最小公倍数 | 洛谷 P1029 [NOIP2001 普及组] 最大公约数和最小公倍数问题
- 大批程序员可能面临被劝退!
- What is industrial radiography equipment?
猜你喜欢
知识蒸馏1:基础原理讲解及yolov5项目实战介绍
Excel导入和导出
Promise entry to proficient (1.5w word detailed explanation)
esp32系列(5):esp32 蓝牙架构学习
Test the.net text to Speech module System. Researched
Dodging ice cream assassins?Crawling ice cream prices through crawlers
论文阅读之《Quasi-Unsupervised Color Constancy 》
PyTorch 猫狗分类源代码及数据集
LeetCode 952. 按公因数计算最大组件大小
Moralis去中心化Web3应用开发教程
随机推荐
超声波探伤仪是做什么用的?
un7.30:Linux——如何在docker容器中显示MySQL的中文字符?
全球架构师峰会
向量检索基础方法总结
Promise入门到精通(1.5w字详解)
Tensorflow模型量化(Quantization)原理及其实现方法
Logback的使用
将 APACHE 日志解析到 SQL 数据库中
What is NDT equipment?
Error occurred while trying to proxy request项目突然起不来了
Error EPERM operation not permitted, mkdir 'Dsoftwarenodejsnode_cache_cacach Two solutions
JMeter笔记3 | JMeter安装和环境说明
Error occurred while trying to proxy request The project suddenly can't get up
知识蒸馏1:基础原理讲解及yolov5项目实战介绍
华为无线设备Mesh配置命令
bean的生命周期
关于内和调试无法查看ntdll内存的问题
18.支持向量机(SVM)的介绍
Servo System of Hydraulic Steering Gear Based on Fuzzy PID
How Google earth engine realizes the arrangement and selection of our time list