• layaBox---TypeScript---接口


    目录

    1.接口示例

    2.可选属性

    3.只读属性

    4.额外的属性检查

    5.函数类

    接口可以描述函数类型

    6.可索引的类型

    7.类类型

    8.继承接口

    9.混合类型

    10.接口继承类


    1.接口示例

    TypeScript核心原则之一是对值所具有的结构进行类型检查。被称作“鸭式辫型法”或“结构性子类型化”。

    1. function printLable( lableObj: { lable:string} )
    2. {
    3. console.log( lableObj.lable );
    4. }
    5. let myObj = { size:10, lable:"Size 10 object" };
    6. printLable( myObj );

    接口示例:

    1. interface LableValue{
    2. lable: string;
    3. }
    4. function printLable( lableObj: LableValue )
    5. {
    6. console.log( lableObj.lable );
    7. }
    8. let myObj = { size:10,lable:"size 10 object"};
    9. printLable( myObj );

    ⚠️注意:类型检查器不会去检查属性的顺序,只要相应的属性存在并且类型也是对的就可以。

    2.可选属性

    接口里的属性不全是必须的,有些只在某些条件下存在,或者根本不存在。

    带有可选属性的接口与普通接口的定义差不多,只是在可选属性名字定义后加一个?符号。

    好处:

    1。可以对可能存在的属性进行预定义。

    2. 可以捕获引用了不存在的属性时的错误。

    例:

    1. interface SquareConfig{
    2. color?: string;
    3. width?: number;
    4. }
    5. function createSquare( config:SquareConfig):{color:string, area:number}
    6. {
    7. let newSquare = {color:"white", area:100};
    8. if(config.color){
    9. newSquare.color = config.color;
    10. }
    11. if(config.width){
    12. newSquare.area = config.width * config.width;
    13. }
    14. return new Square;
    15. }
    16. let mySquare = createSquare({color:"black"});

    3.只读属性

    接口:

    1. //一些对象属性只能在对象刚创建的时候修改其值,可以在属性名前 用 readonly 来指定只读属性
    2. interface Point{
    3. readonly x: number;
    4. readonly y: number;
    5. }
    6. //可以通过赋值来构造一个Point,赋值后 x、y 再也不能被改变了。
    7. let p1:Point = { x:10, y:20 };
    8. p1.x = 5; //error

    数组:

    TypeScript具有ReadonlyArray类型,确保数组创建后再也不能被修改。

    1. let a:number[] = [1,2,3,4];
    2. let ro: ReadonlyArray<number> = a;
    3. ro[0]= 12; //error
    4. ro.push(5); //error
    5. ro.length = 100; //error
    6. a = ro; //error
    7. 上面的最后一行可以看到,把整个ReadonlyArray赋值给一个普通数组也是不可以的。
    8. 但是可以用’类型断言‘重写:
    9. a = ro as number[];

    ⚠️注意:readonly 与 const 的区别:

    作为变量使用时用const, 作为属性使用时用readonly

    4.额外的属性检查

    我们在第一个例子里使用了接口,TypeScript让我们传入{size: number; lable: string}到仅期望得到{lable: string;} 的函数里。 我们也学过了可选属性。

    然而,当你天真的将这两者结合的话就会像javaScript里那样搬起石头砸自己的脚。

    1. //拿createSquare例子来说
    2. interface SquareConfig{
    3. color?: string;
    4. width?: number;
    5. }
    6. function createSquare( config: SquareConfig ):{color: string, area: number}
    7. {
    8. //...
    9. }
    10. let mySquare = createSquare( {coor:"red", width: 100} );
    11. 注意⚠️:这里传的是coor 而不是 color, 在js中这会默默的失败。然而ts会认为这段代码可能存在bug.
    12. 对象字面量会被特殊对待 且 会经过额外属性检查,当它们赋值给变量或作为参数传递时,如果一个对象字面量存在任何‘目标类型’不包含的属性时,你会得到一个Error
    13. //error: 'coor' not expected in type 'SquareConfig'
    14. let mySquare = createSquare( {coor: "red", width: 100} );
    15. 想要绕开这些检查非常简单,最简单的方式就是使用类型断言:
    16. let mySquare = createSquare( {width:100, opacity:0.5} as SquareConfig );

    然而最佳的避开方式是添加一个字符串索引签名,前提是你能够确定这个对象具有某些作为特殊用途的额外属性。

    1. //如果SquareConfig带有上面定义的类型的color和width属性,并且还会带有任意数量的其它属性,那么我们可以这样定义它:
    2. inteface SquareConfig{
    3. color?: string;
    4. width?: number;
    5. [propName: string]: any;
    6. }
    7. 这样SquareConfig就可以带有任意数量的属性,并且只要它们不是color和width ,那么就无所谓它们的类型是什么。

    还有一种可以避开额外属性检查的方式:将这个对象赋值给另一个变量。

    1. let squareOption = { coor:"red", width:100 };
    2. let mySquare = createSquare(squareOption);

    5.函数类

    接口可以描述函数类型

    1. 为了使用接口表示函数类型,我们需要给接口定义一个调用签名。参数列表里的每个参数都需要名字和类型
    2. interface SearchFunc
    3. {
    4. (source: string, subString: string): boolean;
    5. }
    6. 这样定义后,我们可以像使用其它接口一样使用这个函数类型都接口。
    7. 例:
    8. let mySearch:SearchFunc;
    9. mySearch = function(source:string, subString:string)
    10. {
    11. let result = source.search(subString);
    12. return result > -1;
    13. }

    对于函数类型的类型检查来说,函数的参数名不需要与接口里定义的名字相匹配。

    1. let mySearch:SearchFunc;
    2. mySearch = function(src:string, sub:string)
    3. {
    4. let result = src.search(sub);
    5. return result > -1;
    6. }

    函数的参数会逐个进行检查,要求对应位置上的参数类型上兼容的。如果你不想指定类型,TS的类型系统会根据返回值推断出参数类型。

    6.可索引的类型

    与使用接口描述函数类型差不多,我们也可以描述那些能够“通过索引得到”的类型,比如a[10]或ageMap["daniel"].

    1. //可索引类型具有一个 索引签名, 它描述了对象索引的类型。还有相应的索引返回值类型
    2. interface StringArray
    3. {
    4. [index:number]: string
    5. }
    6. let myArray: StringArray;
    7. myArray = ["Bob","Fred"];
    8. let myStr: string = myArray[0];
    9. 这里,我们定义了StringArray接口,它具有索引签名。
    10. 这个索引签名表示了当用 number去索引StringArray时会得到string类型的返回值

    ts支持2种索引签名:字符串 和 数字。

    可以同时使用2种类型的索引,但是数字索引的返回值必须是字符串索引返回值的子类型。

    这是因为当使用number来索引时,js会将它转换成string 然后再去索引对象。

    也就是说用 数字100 去索引 等同于用 字符串“100”去索引,因此两者要保持一致。

    1. //将索引签名设置为只读,这样就可以防止了给索引赋值:
    2. interface ReadonlyStringArray
    3. {
    4. readonly [index:number]:string;
    5. }
    6. let myArray:ReadonlyStringArray = ["Alice","Bob"];
    7. myArray[2] = "Mallory"; //error. 因为索引签名上只读的,所以不能设置

    7.类类型

    7.1.实现接口

    1. //1.与C#或java里的接口一样,ts也能用它来明确的强制一个类去符合某种契约。
    2. interface ClockInterface{
    3. currentTime: Date;
    4. }
    5. class Clock implements ClockInterface{
    6. currentTime: Date;
    7. constructor(h: number, m: number)
    8. {
    9. }
    10. }
    11. //2.也可以在接口中描述一个方法,在类里实现它。
    12. interface ClockInterface{
    13. currentTime: Date;
    14. setTime(d: Date);
    15. }
    16. class Clock implements ClockInterface
    17. {
    18. currentTime: Date;
    19. setTime(d: Date)
    20. {
    21. this.currentTime = d;
    22. }
    23. constructor(h:number, m:number){}
    24. }

    7.2类静态部分与实例部分的区别

    类具有2个类型: 静态部分的类型实例的类型

    1. 当一个类实现了一个接口时,只对其实例部分进行类型检查。
    2. 因此我们应该直接操作类的静态部分,
    3. 例:
    4. interface ClockConstructor
    5. {
    6. new (hour:number, minute:number): ClockInterface;
    7. }
    8. interface ClockInterface
    9. {
    10. tick();
    11. }
    12. function createClock(ctor:ClockConstructor, h: number, m: number ):ClockInterface
    13. {
    14. rerurn new ctor(h, m);
    15. }
    16. class DigitalClock implements ClockInterface
    17. {
    18. constructor(h:number, m: number){}
    19. tick(){
    20. console.log("beep beep");
    21. }
    22. }
    23. let digital = createClock(DigitalClock,7,32);

    8.继承接口

    1. //和类一样,接口也可以相互继承。
    2. interface Shape{
    3. color: string;
    4. }
    5. interface Square extends Shape{
    6. sideLength: number;
    7. }
    8. let square = <Square>{};
    9. square.color = "red";
    10. square.sideLength = 10;
    11. //一个接口也可以继承多个接口,创建出多个接口的合成接口。
    12. interface Shape{
    13. color: string;
    14. }
    15. interface PenStroke{
    16. penWidth: number;
    17. }
    18. interface Square extends Shape,PenStroke{
    19. sideLength: number;
    20. }
    21. let squ = <Square>{};
    22. squ.color = "blue";
    23. squ.penWidtg = 5.0;
    24. squ.sideLength = 10;

    9.混合类型

    1. 例: 一个对象可以同时作为函数和对象使用,并带有额外的属性。
    2. interface Counter{
    3. (start: number): string;
    4. interval: number;
    5. reset(): void;
    6. }
    7. function getCounter(): Counter
    8. {
    9. let cter = <Counter> function( start: number ){};
    10. cter.interval = 125;
    11. cter.reset = function(){};
    12. return cter;
    13. }
    14. let c = getCounter();
    15. c(10);
    16. c.reset();
    17. c.interval = 5.0;
    18. 在使用js第三方库时,你可能需要像上面这样去完整的定义类型

    10.接口继承类

    当接口继承了一个类类型时,它会继承类的成员但不包括其实现。

    接口同样会继承到类的private和protected成员。 也就意味着,当你创建了一个接口继承了一个拥有私有或保护的成员的类时,这个接口类型只能被这个类或其子类所实现(implement)

    1. //类
    2. class Control
    3. {
    4. private state: any;
    5. }
    6. //接口继承类
    7. interface SelectableControl extends Control
    8. {
    9. select(): void;
    10. }
    11. //类继承类 再实现接口
    12. class Button extends Control implements SelectableControl
    13. {
    14. select(){}
    15. }
    16. //类继承类
    17. class TextBox extends Control
    18. {
    19. select(){}
    20. }
    21. //error "Image"类型缺少“state”属性
    22. class Image implements SelectableControl
    23. {
    24. select(){}
    25. }
    26. 上面的例子中 selectableControl 包含了Control的所有成员,包括私有成员 state。
    27. 因为state是私有成员,所以只有Control的子类才能实现SelectableControl接口。

  • 相关阅读:
    某大型制造企业数字化转型规划方案(附下载)
    npm 设置取消代理
    LeetCode 热题 HOT 100 第八十天 494. 目标和 中等题 用python3求解
    Linux篇 四、Linux修改用户名
    uniapp使用plus.sqlite实现图片、视频缓存到手机本地
    从2023蓝帽杯0解题heapSpary入门堆喷
    【STM32】锁存器
    兼容国产化神通数据库遇到的问题适配
    计算机毕业设计成品基于Uniapp+SSM实现的新闻APP
    UFS Power Management 介绍
  • 原文地址:https://blog.csdn.net/lalate/article/details/126037806