babelcodes
9/18/2017 - 5:34 PM

TypeScript > Interface

TypeScript > Interface ▶︎ http://babel.codes/TypeScript/Interface

/**
 * Table of content:
 *
 * 1/ Definition
 * 2/ Optional Properties with ?
 * 3/ Readonly properties
 * 4/ Excess Property Checks
 * 5/ Function Types
 * 6/ Indexable Types
 * 7/ Class Types
 * 8/ Extending Interfaces
 * 9/ Hybrid Types
 * 10/ Interfaces Extending Classes
 *
 */

interface LabelledValue {                                  // 1/ Definition
    readonly label      : string;                          // 3/ Readonly properties
    width?              : number;                          // 2/ Optional Properties
    [propName: string]  : any;                             // 4/ Excess Property Checks
}

function printLabel(labelledObject: LabelledValue) {       // 1/ Definition: USAGE
    console.log(labelledObject.label);
    if (labelledObject.width) {                            // 2/ Optional Properties: USAGE
        console.log(labelledObject.width);
    }

    labelledObject.label = "Done"; // error!               // 3/ Readonly properties: USAGE
}

// printLabel({ size: 10, label: "Size 10 Object" });      // 4/ Excess Property Checks: USAGE - error
printLabel({ size: 10, label: "Size 10 Object" } as LabelledValue); // 4/ Excess Property Checks: USAGE - ok


interface SearchFunc {
    (source: string, subString: string): boolean;
}

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


interface NumberDictionary {                               // 6/ Indexable Type
    [index: string]: number;
    length         : number;     // ok, length is a number
    name           : string;     // error, the type of 'name' is not a subtype of the indexer
}
interface ReadonlyStringArray {
    readonly [index: number]: string;                      // 6/ Indexable Type - readonly
}
let myArray: ReadonlyStringArray = ["Alice", "Bob"];
myArray[2] = "Mallory";          // error!


                                                           // 7/ Class and constructor interface
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"); }
}
let digital = createClock(DigitalClock, 12, 17);


                                                           // 8/ Extending Interfaces
interface Shape     { color: string; }
interface PenStroke { penWidth: number; }
interface Square extends Shape, PenStroke { sideLength: number; }
let square = <Square>{};
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;


                                                           // 9/ Hybrid Types
interface Counter {
    (start: number): string;    // Function type
    interval: number;           // Property
    reset(): void;              // Method
}

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

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


                                                           // 10/ Interfaces Extending Classes
class Control {
    private state: any;
}
interface SelectableControl extends Control {
    select(): void;
}
class Button extends Control implements SelectableControl {
    select() { }
}
class TextBox extends Control {
}
// Error: Property 'state' is missing in type 'Image'.
class Image implements SelectableControl {
    select() { }
}