深入解析TypeScripe幾個特點 - Alex
TypeScript是一種功能強大的靜態型別化語言。很多時候,它被稱為“ JavaScript的超集”。但是,對於某些功能,它會強制以特定方式編寫程式碼。
類魔法
TypeScript對class關鍵字有特殊的支援。對於(模組的)全域性範圍內的每個類,它隱式定義一個具有相同名稱的例項型別。這樣可以編寫類似const user: User = new User()。
不幸的是,該機制不適用於動態建立的類或普通建構函式。在這種情況下,必須使用實用程式InstanceType和關鍵字typeof。
//正常類 class StaticClass {} const a: StaticClass /* 型別例項 */ = new StaticClass(); /* 構造器 */ //下面是 |
const createClass = () => class {}; const DynamicClass = createClass(); /* 無隱性型別定義 */ // 現在這種寫法無效: const b: DynamicClass = new DynamicClass(); type DynamicClass = InstanceType<typeof DynamicClass>; /* 現在有了型別 */ const b: DynamicClass /* 型別例項 */ = new DynamicClass(); /* 構造器*/ export {StaticClass, DynamicClass}; /* 都輸出構造器和型別 */ |
語句type X = InstanceType<typeof X>在邏輯上等效於TypeScript在遇到class關鍵字時自動執行的操作。
沒有成員的型別推斷
對於介面的某些實現,可以推斷成員屬性和成員函式的型別。例如,當介面Logger定義函式log(message: string): void時,其實現型別ConsoleLogger只可以使用方法簽名log(message)。TypeScript可以推斷出function引數是一個字串,返回值是void。由於不同的原因,目前不支援此功能。必須明確地顯式型別化所有成員屬性和成員函式,而與介面或基類無關。
下一個示例說明了由於這種情況導致的潛在重複:
interface Logger { logInfo(message: String): void; logWarning(message: String): void; logError(message: String): void; } class ConsoleLogger implements Logger { logInfo(message: String) { /* .. */ } logWarning(message: String) { /* .. */ } logError(message: String) { /* .. */ } } |
沒有部分型別推斷
TypeScript可以根據其用法來推斷型別引數的型別。例如,
asArray<T>(item: T) { return [item]; } |
可以在不指定型別引數(例如)的情況下呼叫該函式asArray('foo')。在這種情況下,T被推斷為型別"foo"(extends string)。但是,這不適用於多個型別的引數,只能推斷其中的一些。一種可能的解決方法是將一個函式拆分為多個,其中一個具有要推斷的所有型別引數。
以下程式碼顯示了一個通用函式,用於使用預填充的資料建立物件工廠:
const createFactory1 = <R extends {}, P extends {}>(prefilled: P) => (required: R) => ({...required, ...prefilled}); // requires to specify second type parameter, even though it could be inferred const createAdmin1 = createFactory1<{email: string}, {admin: true}>({admin: true}); const adminUser1 = createAdmin1({email: 'john@example.com'}); const createFactory2 = <R extends {}>() => <P extends {}>(prefilled: P) => (required: R) => ({...required, ...prefilled}); // first function specifies type parameter, for second function it is inferred const createAdmin2 = createFactory2<{email: string}>()({admin: true}); const adminUser2 = createAdmin2({email: 'jane@example.com'}); |
函式createFactory1()需要指定兩個型別引數,即使可以推斷出第二個引數。createFactory2()透過將該功能分為兩個單獨的操作,消除了此問題。
區分聯合Discriminating Unions用法
區分聯合對於處理類似專案的異類集(例如“領域事件”)很有用。該機制允許使用區分欄位來區分多種型別。每種專案型別都為該欄位使用一種特定的型別,以使其與眾不同。處理具有聯合型別的專案時,可以根據區分欄位來縮小其型別。這種機制的一個缺點是,它要求以特定的方式編寫程式碼。
下一個示例將事件處理程式的JavaScript實現與其具有Discriminate Unions的TypeScript比較:
// JavaScript const handleEvent = ({type, data}) => { // early destructuring if (type == 'UserRegistered') console.log(`new user with username: ${data.username}`); if (type == 'UserLoggedIn') console.log(`user logged in from device: ${data.device}`); }; // TypeScript type UserRegisteredEvent = {type: 'UserRegistered', data: {username: string}}; type UserLoggedInEvent = {type: 'UserLoggedIn', data: {device: string}}; type UserEvent = UserRegisteredEvent | UserLoggedInEvent; const handleEvent = (event: UserEvent) => { // destructuring must not happen here if (event.type == 'UserRegistered') console.log(`new user with username: ${event.data.username}`); if (event.type == 'UserLoggedIn') console.log(`user logged in from device: ${event.data.device}`); }; |
使用TypeScript時,在下溯其型別之前,請勿將具有Discriminate Union型別的值進行分解。
模板文字Template Literal型別
模板文字型別本質上是型別級別上的模板文字。它們可用於建立字串文字型別,這些型別是評估模板文字的結果。David Timms的文章“在TypeScript 4.1中探索模板文字型別”透過高階示例對它們進行了更詳細的說明。一種值得注意的用例是訊息處理元件的定義,其中各個訊息型別由特定操作處理。
以下示例使用先前的記錄器示例對此進行了演示:
type MessageType = 'Info' | 'Warning' | 'Error'; type Logger = { [k in MessageType as `log${MessageType}`]: (message: string) => void; } class ConsoleLogger implements Logger { logInfo(message: String) { /* .. */ } logWarning(message: String) { /* .. */ } logError(message: String) { /* .. */ } } |
型別定義Logger在聯合型別MessageType上進行迭代,併為每種MessageType定義一個操作。
總結
儘管TypeScript的好處可能勝過其潛在的弊端,但要意識到這些弊端仍然很重要:首先,區分聯盟會影響使用解構分配的方式。同樣,缺少部分型別推斷可能需要將一個功能拆分為多個功能。
相關文章
- python的五個特點,你知道幾個?Python
- 製藥行業的幾個特點行業
- 乾淨程式碼的幾個特點 -Xebia
- 雲桌面的幾大特點!
- Clean清潔領域模型的幾個特點 -Kamil Grzybek模型
- Linux系統的六大特點,你知道幾個?Linux
- 在數字化時代的ITSM的幾個特點
- 什麼是雲解析?雲解析有哪些特點?
- 什麼是DNS雲解析?雲解析有哪些特點?DNS
- webpack 拆包:關於 splitChunks 的幾個重點屬性解析Web
- XSS攻擊有什麼特點?XSS攻擊分為幾個型別?型別
- 運維行業有什麼特點呢?應該重視哪幾個方面?運維行業
- 開源表單流程設計器有哪幾個突出的優勢特點?
- 深入 TypeScript – 2( 幾個常用的小技巧)TypeScript
- typescripe第二天
- 輪換代理的3個特點
- 深入瞭解標準流以及脫標元素的特點
- DNS入門學習:什麼是雲解析?雲解析有哪些特點?DNS
- Tungsten Fabric架構解析|TF主要特點和用例架構
- MES與PLC整合時的幾種握手方式及特點
- 通過幾個問題深入淺出VueVue
- 4大特點解析華為雲資料湖“黑科技”
- qt深入解析QT
- 深入解析Scheduler
- 物化檢視幾個知識點
- Collectors.toMap的幾個注意點
- Dart 語言的7個很酷的特點Dart
- concurrentHashMap特點HashMap
- ThreadLocal原理深入解析thread
- 高效好用影片加密軟體的4個特點加密
- 通過幾個問題深入分析Vue中的keyVue
- Windows原理深入學習系列-特權Windows
- Spring MVC ControllerAdvice深入解析SpringMVCController
- 深入解析DLL劫持漏洞
- 深入解析Kubernetes admission webhooksWebHook
- 好的Java架構具備的5個特點!Java架構
- 伺服器的頻寬接入有幾種型別,特點是什麼伺服器型別
- 深度解析原型中的各個難點原型