TS常用操作小贴士

305 阅读3分钟

解构数组

let input = [1, 2]; 

let [first, second] = input; 

console.log(first); // outputs 1 

console.log(second); // outputs 2




let [first, ...rest] = [1, 2, 3, 4]; 

console.log(first); // 

outputs 1 console.log(rest); // outputs [ 2, 3, 4 ]

对象解构


let o = { a: "foo", b: 12, c: "bar" };

let { a, b } = o;




let { a, ...passthrough } = o;

let total = passthrough.b + passthrough.c.length;

属性重命名

let { a: newName1, b: newName2 } = o;

\

let {a, b}: {a: string, b: number} = o;

\

默认值

function keepWholeObject(wholeObject: { a: string, b?: number }) { 

    let { a, b = 1001 } = wholeObject; 

}



function f({ a="", b=0 } = {}): void// ... f();

函数声明


type C = { a: string, b?: numberfunction f({ a, b }: C): void// ... 

}




function f({ a="", b=0 } = {}): void// ... f();

接口


interface SquareConfig {

    color?: string;

    width?: number;

    [propName: string]: any;

}

对象也可以展开,但只会展开可枚举属性,方法会丢失。

接口索引


interface StringArray { [index: number]: string; } 

let myArray: StringArray; 

myArray = ["Bob", "Fred"]; 

let myStr: string = myArray[0];

\


//TypeScript支持两种索引签名:字符串和数字。 可以同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型。 这是因为当使用 number来索引时,JavaScript会将它转换成string然后再去索引对象。 也就是说用 100(一个number)去索引等同于使用"100"(一个string)去索引,因此两者需要保持一致。

class Animal { name: string; } 

class Dog extends Animal { breed: string; } 

// 错误:使用数值型的字符串索引,有时会得到完全不同的Animal! 

interface NotOkay { [x: number]: Animal; [x: string]: Dog; }




//使用索引后接口内部所有属性的类型都必须与索引属性类型相同




//只读索引可以防止索引被直接设置

interface ReadonlyStringArray { readonly [index: number]: string; } 

let myArray: ReadonlyStringArray = ["Alice", "Bob"]; 

myArray[2] = "Mallory"; // error!

类接口


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);



//因为createClock的第一个参数是ClockConstructor类型,在createClock(AnalogClock, 7, 32)里,会检查AnalogClock是否符合构造函数签名。

接口继承


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;

混合类型


interface Counter { (start: number): string; interval: number; reset(): void; } 

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;

接口继承类

当接口继承了一个类类型时,它会继承类的成员但不包括其实现。 就好像接口声明了所有类中存在的成员,但并没有提供具体实现一样。 接口同样会继承到类的private和protected成员。 这意味着当你创建了一个接口继承了一个拥有私有或受保护的成员的类时,这个接口类型只能被这个类或其子类所实现(implement)。