TS官方文檔小記

1. TS修改ReadonlyArray

let a: ReadonlyArray<number> = [1, 2];

let b = a as number[];

b.push(3);

console.log(a);  // [1 ,2 ,3]
console.log(b);  // [1 ,2 ,3]
// 編譯后
var a = [1, 2];
var b = a;
b.push(3);
console.log(a);
console.log(b);
  • 類型斷言只是繞開了編譯上的報錯,本質(zhì)上并沒有對賦值操作帶來任何影響

2. 接口描述了類的公共部分,而不是公共和私有兩部分。 它不會幫你檢查類是否具有某些私有成員。

interface MyKlass {
    name: string;
    age: number;
}

// ERROR: Class 'Test' incorrectly implements interface 'MyKlass'.
//  Property 'age' is private in type 'Test' but not in type 'MyKlass'.
class Test implements MyKlass {  
    name: 'han';
    private age: 1
}
  • 這個問題的報錯有些奇怪,意思好像是讓我們?yōu)轭愋鸵布右粋€private。但實際上接口并不能規(guī)定私有成員應(yīng)該有的類型,不應(yīng)該用這個interface來檢查私有成員

3. 混合類型

  • 一個對象可以同時做為函數(shù)和對象使用,并帶有額外的屬性。
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;

4. 關(guān)于類

  • 在我們聲明一個類Test時,我們還同時聲明了一個類型Test,所有該類的實例的類型都是Test

  • typeof TestTest區(qū)別: 類是有自己的類型的, 類的類型與實例的類型并不相同:

class Test {
    static age = 18;
    public name = 'gaarahan';
}

const testIns = new Test();

const instanceTypeTest: Test = testIns;
/* Property 'age' is a static member of type 'Test' */
console.log(instanceTypeTest.age);   // Error: Test 是實例的類型,實例上是訪問不到靜態(tài)屬性的

/*
Type 'Test' is not assignable to type 'typeof Test'.
  Property 'prototype' is missing in type 'Test'.
*/
const klassTypeTest: typeof Test = testIns;  // 類的類型(typeof Test)與實例類型(Test)并不兼容

const klassTypeTest1: typeof Test = Test;  // typeof Test 與 Test 是兼容的
console.log(klassTypeTest1.age);  
  • 類的類型就是構(gòu)造函數(shù)的類型 ?

5. 顯式的使用this以支持類型檢查

interface ITest {
  name: string
}

class Test implements ITest {
    name: 'han';
    saySth(this: Test) {
        return () => {
          alert(this.name)
        }
    }
}

const t = new Test();
const saySth = t.saySth();

saySth();
  • 在該例中,不為saySth傳遞this參數(shù),函數(shù)也可以正常工作,但此時的this,會被推斷為any類型,顯式的傳遞this,可以使其支持類型檢查。

6. 對于工廠函數(shù)來說,我們也可以檢查傳入構(gòu)造函數(shù)的參數(shù),來避免出錯

class Clock {
    date: Date;
    constructor(date: Date) {
        this.date = date;
    }
}

function factoryWithoutType<T>(c): T {
    return new c('han');  // 使用錯誤的參數(shù)來初始化
}

function factoryWithType<T>(c: { new (name: string) }): T {
    return new c('han');   // 使用錯誤的參數(shù)來初始化
}

const clockHan1 = factoryWithoutType<Clock>(Clock);
console.log(clockHan1.date);  // 'han'

const clockHan2 = factoryWithType<Clock>(Clock); // 傳入的參數(shù)類型檢查報錯
  • 在沒有類型檢查時,工廠能夠成功執(zhí)行,但結(jié)果顯然不是我們想要的東西(date 是一個無意義的 string)

7. const枚舉 與 外部枚舉

  • const枚舉并不會生成一個額外的變量,而是會在編譯階段將其變成常量寫在代碼中
  • const枚舉只能使用常量枚舉表達式,不允許包含計算成員;
  • const枚舉不能使用反向映射。
  • const枚舉與普通枚舉的編譯對比:
// 編譯前
const enum Enum {
    A = 1
}
console.log(Enum.A);
console.log(Enum[1]); // Error: A const enum member can only be accessed using a string literal.
// --------------------------------------

enum Test {
    A
}
console.log(Test.A);
// 編譯后
console.log(1 /* A */);
console.log(Enum[1]);
// --------------------------------------
var Test;
(function (Test) {
    Test[Test["A"] = 0] = "A";
})(Test || (Test = {}));
console.log(Test.A);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容