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 Test
與Test
區(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);