ts入門からステップアップ-3-9インタフェース(一)


インタフェース(一)クイックスタート
インタフェースプローブ(値の外形のみに注目)
interface LabelledValue {
  label: string;
}

function printLabel(labelledObj: LabelledValue) {
  console.log(labelledObj.label);
}

let myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj);

オプション属性(オプション属性名定義の後に?記号を付けるのみ).
interface SquareConfig {
  color?: string;
  width?: number;
}

読み取り専用属性(一部のオブジェクト属性は、オブジェクトが作成されたばかりのときにのみ値を変更できます.属性名はreadonlyで読み取り専用を指定します.値を割り当てた後は変更できません)
interface Point {
    readonly x: number;
    readonly y: number;
}
let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error!

ReadonlyArray
let a: number[] = [1, 2, 3, 4];
let ro: ReadonlyArray = a;
ro[0] = 12; // error!
ro.push(5); // error!
ro.length = 100; // error!
a = ro; // error!
readonly  vs  const
変数としてはconst,属性としてはreadonlyを用いる.
追加のプロパティチェック
変数に値を割り当てたり、パラメータとして渡したりするとき.オブジェクトのフォント量に「ターゲットタイプ」に含まれない属性がある場合、エラーが発生します.SquareConfigが、上記で定義したタイプのcolorおよびwidthの属性を有し、さらに任意の数の他の属性を有する場合、このように定義することができる.
(本当によく使う)
interface SquareConfig {
    color?: string;
    width?: number;
    [propName: string]: any;
}

関数のタイプ
関数タイプのタイプチェックでは、関数のパラメータ名がインタフェースで定義された名前と一致する必要はありません. 
interface SearchFunc {
  (source: string, subString: string): boolean;
}

let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
  let result = source.search(subString);
  return result > -1;
}

インデックス可能なタイプ
Typeスクリプトでは、文字列と数値の2つのインデックス署名がサポートされています.
オブジェクトインデックスのタイプと、対応するインデックス戻り値のタイプについて説明します.
interface StringArray {
  [index: number]: string;
}

let myArray: StringArray;
myArray = ["Bob", "Fred"];

let myStr: string = myArray[0];

クラスタイプ
実装インタフェース
インタフェースでメソッドを記述し、クラスで実装することもできます.
interface ClockInterface {
    currentTime: Date;
    setTime(d: Date);
}

class Clock implements ClockInterface {
    currentTime: Date;
    setTime(d: Date) {
        this.currentTime = d;
    }
    constructor(h: number, m: number) { }
}

クラス静的部分とインスタンス部分の違い
クラスにインタフェースが実装されている場合、そのインスタンス部分のみがタイプチェックされます(constructorはクラスの静的部分に存在します).
複雑だね
interface ClockConstructor {
    new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
    tick();
}

function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
    return new ctor(hour, minute);
}

class DigitalClock implements ClockInterface {
    constructor(h: number, m: number) { }
    tick() {
        console.log("beep beep");
    }
}
class AnalogClock implements ClockInterface {
    constructor(h: number, m: number) { }
    tick() {
        console.log("tick tock");
    }
}

let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);

インタフェースの継承
let strLength: number = (someValue).length;タイプブレークスルー
interface Shape {
    color: string;
}

interface Square extends Shape {
    sideLength: number;
}

let square = {};
square.color = "blue";
square.sideLength = 10;

ブレンドタイプ
まずこれを思い出す([propName:string]:any;任意の数の他の属性を持つ)
interface SquareConfig {     color?: string;     width?: number;     [propName: string]: any; }
そしてこれを見て(start:number):string;1つの関数を表します)
interface Counter {
    (start: number): string;
    interval: number;
    reset(): void;
}

混合タイプを見てみましょう
1つのオブジェクトは、関数とオブジェクトの両方として使用でき、追加のプロパティがあります.
interface Counter {
    (start: number): string;
    interval: number;
    reset(): void;
}

function getCounter(): Counter {
    let counter = function (start: number) { };
    counter.interval = 123;
    counter.reset = function () { };
    return counter;
}

let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;

 
インタフェース継承クラス(これは複雑すぎて後で見ます)
インタフェースがクラスタイプを継承すると、クラスのメンバーは継承されますが、実装は含まれません.
これは、プライベートまたは保護されたメンバーを持つクラスを継承するインタフェースを作成した場合、このインタフェースタイプはこのクラスまたはそのサブクラスによってのみ実現されることを意味します.
-----------------------------------------------------------------------------------------------------------------
TypeScriptの核心原則の一つは,値が持つ構造のタイプチェックである.「アヒル型弁法」や「構造的サブタイプ化」と呼ばれることがある.Type Scriptでは、インタフェースの役割は、これらのタイプの名前とコードまたはサードパーティのコードの契約を定義することです.
1.インタフェースの初期プローブ
注意事項
1)インタフェース定義のフィールドで、伝達するパラメータは必ずあり、規定に合致しなければならない.(つまり、インタフェースはいくつかのフィールドを定義しています.いくつか伝えなければなりません)
例えば次は間違いを報告します
interface config {
    label: string;
    size: number;
}

function printLabel(labelledObj: config) {
    console.log(labelledObj.label);
  }
  
printLabel({label: '  '});//  ,      

 
2)上記1)の条件が満たされた後,関係のないフィールドをいくつか渡すと誤報となる.
interface config {
    label: string;
    size: number;
}

function printLabel(labelledObj: config) {
    console.log(labelledObj.label);
  }
  
//    “{ label: string; size: number; other: string; }”         “config” //  。             ,  “other”    “config” 。ts(2345)
printLabel({ label: '  ', size: 12, other: '12' });

 
3)ただし,伝達するパラメータを1つのmyobj変数として提案すると,実行する箇所は誤報にはならないが,関数では使用できず,誤報になる.だから安全のために.あなたのインタフェースはいくつかのフィールドを定義し、いくつか伝えます.
interface config {
    label: string;
}

function printLabel(labelledObj: { label: string }) {
    console.log(labelledObj.label);
    console.log(labelledObj.size);//    。  “{ label: string; }”      “size”。ts(2339)
  }
  
let myObj = { size: 10, label: "Size 10 Object" };
printLabel(myObj);//   
##     

                     :

```typescript
function printLabel(labelledObj: { label: string }) {
  console.log(labelledObj.label)
}

let myObj = { size: 10, label: 'Size 10 Object' }
printLabel(myObj)
```

         `printLabel`    。`printLabel`      ,               `label`     `string`    。       ,                   ,                    ,         。   ,     TypeScript          ,         。

           ,         :      `label`        `string`:

```typescript
interface LabelledValue {
  label: string
}

function printLabel(labelledObj: LabelledValue) {
  console.log(labelledObj.label)
}

let myObj = {size: 10, label: 'Size 10 Object'}
printLabel(myObj)
```

`LabelledValue`          ,            。         `label`       `string`    。       ,                 ,    `printLabel`           。           。                   ,         。

         ,               ,                    。

2.オプション属性
注意事項
  • オプションの属性は、いくつかの条件の下にのみ存在するか、または
  • がまったく存在しないものである.
  • の利点の1つは、存在する可能性のある属性を事前定義できる
  • である.
  • の利点の2つは、存在しない属性を参照するエラー
  • をキャプチャできることである.
    個人的には、事前定義は問題ありません.公式サイトで言うメリットの2つは、存在しない属性を引用したときのエラーをキャプチャできることです.実際にはオプション属性でなくても、存在しない属性を引用したときにエラーが発生します.インタフェースの最初の2を参照してください.
    ##     
    
                 。             ,       。                      。
    
    ```typescript
    interface Square {
      color: string,
      area: number
    }
    
    interface SquareConfig {
      color?: string
      width?: number
    }
    
    function createSquare (config: SquareConfig): Square {
      let newSquare = {color: 'white', area: 100}
      if (config.color) {
        newSquare.color = config.color
      }
      if (config.width) {
        newSquare.area = config.width * config.width
      }
      return newSquare
    }
    
    let mySquare = createSquare({color: 'black'})
    ```
    
                        ,                  `?`   。
    
                             ,                      。   ,      `createSquare`    `color`      ,          :
    
    ```typescript
    interface Square {
      color: string,
      area: number
    }
    
    interface SquareConfig {
       color?: string;
       width?: number;
    }
     
    function createSquare(config: SquareConfig): Square {
       let newSquare = {color: 'white', area: 100}
       if (config.clor) {
         // Error:    'clor'        'SquareConfig'  
         newSquare.color = config.clor
       }
       if (config.width) {
         newSquare.area = config.width * config.width
       }
       return newSquare
     }
     
     let mySquare = createSquare({color: 'black'})
    ```

    3.読み取り専用属性
    ##     
    
                          。           `readonly`        :
    
    ```typescript
    interface Point {
      readonly x: number
      readonly y: number
    }
    ```
    
                        `Point`。    ,`x`   `y`         。
    
    ```typescript
    let p1: Point = { x: 10, y: 20 }
    p1.x = 5 // error!
    ```
    
    TypeScript    `ReadonlyArray`   ,   `Array`   ,            ,                  :
    
    ```typescript
    let a: number[] = [1, 2, 3, 4]
    let ro: ReadonlyArray = a
    ro[0] = 12 // error!
    ro.push(5) // error!
    ro.length = 100 // error!
    a = ro // error!
    ```
    
             ,          `ReadonlyArray`                。             :
    
    ```typescript
    a = ro as number[]
    ```
    
    ### readonly vs const
    
            `readonly`    `const`                       。           `const`,         `readonly`。

    4.追加の属性チェック
    追加のプロパティチェックとは、{ size: number; label: string; }から{ label: string; }のみが期待される関数に入力されることです.これは間違いを報告するに違いありません.この問題は上でも議論したことがある.次の例を見てください
    interface SquareConfig {
        color?: string;
        width?: number;
    }
    
    function createSquare(config: SquareConfig): { color: string; area: number } {
        // ...
    }
    
    // error: 'colour' not expected in type 'SquareConfig'
    let mySquare = createSquare({ colour: "red", width: 100 });

    しかし、実際の開発過程では、このような場面は避けられない.どうやって解決するのだろうか.以下の方法で使用できます.
    1)タイプブレークスルーの使用
    let mySquare = createSquare({ colour: "red", width: 100 }as SquareConfig);

    しかし、この方法には弊害があり、呼び出し時にエラーは報告されませんが、関数に存在しない属性colourを呼び出すと、エラーが報告されます.例えば、
    interface SquareConfig {
        color?: string;
        width?: number;
      }
      
      function createSquare(config: SquareConfig): { color: string; area: number } {
        let newSquare = {color: "white", area: 100};
        //   “colour”   “SquareConfig”    。      “color”?ts(2551)
        if (config.colour) {
          newSquare.color = config.colour;
        }
        if (config.width) {
          newSquare.area = config.width * config.width;
        }
        return newSquare;
      }
      
    let mySquare = createSquare({ colour: "red", width: 100 }as SquareConfig);

    2)文字列インデックス署名を追加します.このオブジェクトに特定の用途で使用される追加のプロパティがある可能性があることを確認することを前提としています.SquareConfigが、上記で定義したタイプのcolorおよびwidthの属性を有し、さらに任意の数の他の属性を有する場合、このように定義することができる.
    interface SquareConfig {
        color?: string;
        width?: number;
        [propName: string]: any;
    }

    この方式がよいのは,1)が出現しない問題であり,関数で呼び出すことができるからである.
    interface SquareConfig {
        color?: string;
        width?: number;
        [propName: string]: any;
    }
    
    //        
    function createSquare(config: SquareConfig): { color: string; area: number } {
        let newSquare = { color: "white", area: 100 };
        if (config.colour) {
            newSquare.color = config.colour;
        }
        if (config.width) {
            newSquare.area = config.width * config.width;
        }
        return newSquare;
    }
    
    let mySquare = createSquare({ colour: "red", width: 100 } as SquareConfig);

    3)このオブジェクトを別の変数に割り当てます.squareOptionsは追加のプロパティチェックを受けないため、コンパイラはエラーを報告しません.
    let squareOptions = { colour: "red", width: 100 };
    let mySquare = createSquare(squareOptions);

    しかし、関数呼び出し時にエラーが発生します.
    interface SquareConfig {
        color?: string;
        width?: number;
    }
    
    //        
    function createSquare(config: SquareConfig): { color: string; area: number } {
        let newSquare = { color: "white", area: 100 };
        //   “colour”   “SquareConfig”    。      “color”?ts(2551)
        if (config.colour) {
            newSquare.color = config.colour;
        }
        if (config.width) {
            newSquare.area = config.width * config.width;
        }
        return newSquare;
    }
    
    let squareOptions = { colour: "red", width: 100 };
    let mySquare = createSquare(squareOptions);
    ##        
    
                  ,TypeScript       `{ size: number; label: string; }`        `{ label: string; }`     ,              。
    
      ,                JavaScript             。   ,  `createSquare`     :
    
    ```typescript
    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 newSquare
    }
    
    
    let mySquare = createSquare({ colour: 'red', width: 100 })
    ```
    
         `createSquare`        `colour`     `color`。   JavaScript  ,       。
    
                       ,   `width`       ,    `color`   ,      `colour`        。
    
      ,TypeScript             bug。                       ,                   。              “    ”       ,        。
    
    ```typescript
    // error: 'colour'        'SquareConfig'  
    let mySquare = createSquare({ colour: 'red', width: 100 })
    ```
    
              。              :
    
    ```typescript
    let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig)
    ```
    
      ,                   ,                               。    `SquareConfig`            `color`   `width`   ,               ,           :
    
    ```typescript
    interface SquareConfig {
      color?: string
      width?: number
      [propName: string]: any
    }
    ```
    
               ,          `SquareConfig`           ,         `color`   `width`,              。
    
                   ,          ,                  :    `squareOptions`           ,         。
    
    ```typescript
    let squareOptions = { colour: 'red', width: 100 }
    let mySquare = createSquare(squareOptions)
    ```
    
       ,            ,             。                      ,           ,                 bug。                  ,              。    ,       `color`   `colour`     `createSquare`,      `SquareConfig`          。
    

    5.関数タイプ
    ##     
    
           JavaScript              。               ,           。
    
                ,               。                       。                  。
    
    ```typescript
    interface SearchFunc {
      (source: string, subString: string): boolean
    }
    ```
    
         ,                        。                   ,                 。
    
    ```typescript
    let mySearch: SearchFunc
    mySearch = function(source: string, subString: string): boolean {
      let result = source.search(subString);
      return result > -1
    }
    ```
    
                 ,                     。   ,                :
    
    ```typescript
    let mySearch: SearchFunc
    mySearch = function(src: string, sub: string): boolean {
      let result = src.search(sub);
      return result > -1
    }
    ```
    
                ,                。          ,TypeScript              ,            `SearchFunc`     。                     (    `false`   `true`)。                ,                    `SearchFunc`          。
    
    ```typescript
    let mySearch: SearchFunc
    mySearch = function(src, sub) {
      let result = src.search(sub)
      return result > -1
    }
    ```

    6.インデックス可能なタイプ
    ##       
    
                  ,           “      ”   ,   `a[10]`   `ageMap['daniel']`。               ,           ,            。         :
    
    ```typescript
    interface StringArray {
      [index: number]: string
    }
    
    let myArray: StringArray
    myArray = ['Bob', 'Fred']
    
    let myStr: string = myArray[0]
    ```
    
         ,      `StringArray`   ,       。             `number`     `StringArray`      `string`       。
    
    TypeScript         :      。              ,                           。         `number`     ,JavaScript       `string`         。       `100`(   `number`)        `'100'`(   `string` )   ,          。
    
    ```typescript
    class Animal {
      name: string
    }
    class Dog extends Animal {
      breed: string
    }
    
    //   :           ,          Animal!
    interface NotOkay {
      [x: number]: Animal
      [x: string]: Dog
    }
    ```
    
                   `dictionary`   ,                      。            `obj.property`   `obj['property']`        。       , `name`               ,               :
    
    ```typescript
    interface NumberDictionary {
      [index: string]: number;
      length: number;    //   ,length number  
      name: string       //   ,`name`                 
    }
    ```
    
      ,             ,           :
    
    ```typescript
    interface ReadonlyStringArray {
      readonly [index: number]: string;
    }
    let myArray: ReadonlyStringArray = ['Alice', 'Bob'];
    myArray[2] = 'Mallory'; // error!
    ```