An gu la r
User Group Taiwan
TypeScript 綜合格鬥技
多奇數位創意有限公司
技術總監 黃保翕 ( Will 保哥 )
部落格:http://blog.miniasp.com/
Angular 線上讀書會 第 3 季
An gu la r
User Group Taiwan
TypeScript 編譯器
An gu la r
User Group Taiwan
找出 TypeScript 編譯器的路徑與版本
若 PATH 環境變數有問題,使用 Rapid Environment Editor 可快速修復!
npm list -g --depth=0
where tsc
tsc -v
An gu la r
User Group Taiwan
tsc --init
初始化 tsconfig.json 設定檔
An gu la r
User Group Taiwan
編譯所有檔案 (讀取 tsconfig.json 設定檔) (預設編譯含子目錄下的所有檔案)
• tsc
編譯單一檔案 (需指定 TypeScript 編譯器選項)
• tsc [options] [file ...]
顯示完整的 TypeScript 編譯器選項
• tsc --all
顯示 tsc 編譯器摘要說明
• tsc -h
編譯 TypeScript 程式
An gu la r
User Group Taiwan
問題說明
• ng new --minimal demo1
• code demo1
• 透過 VSCode 檔案總管將 src/environments 目錄移到 src/app/ 目錄下
• npm start
Angular 下的 TypeScript 偵錯技巧
Allow to disable drag and drop in the files explorer #4842
( "explorer.enableDragAndDrop": false )
An gu la r
User Group Taiwan
Glob support in tsconfig.json
• * 代表 0 個到多個字元比對 (不含目錄分隔字元)
• ? 代表 1 個字元比對 (不含目錄分隔字元)
• **/ 代表比對任意子目錄
設定 Base URL 預設 import 的基底路徑
設定 Path mapping
• 必須搭配 "baseUrl" 設定一起使用
• Angular CLI 專案只能設定在根目錄的 tsconfig.json 設定檔中
tsconfig.json 設定技巧
An gu la r
User Group Taiwan
預設載入內建的模組定義檔 ( --lib )
es2015.core
es2015.collection
es2015.iterable
es2015.promise
es2015.proxy
es2015.reflect
es2015.generator
es2015.symbol
es2015.symbol.wellknown
dom (Angular 5)
webworker
es5
es6 / es2015
es2016
es2016.array.include
es2017 (Angular 5)
es2017.object
es2017.sharedmemory
scripthost
An gu la r
User Group Taiwan
TypeScript 型別應用
An gu la r
User Group Taiwan
let decimal = 100;
let isDone = false;
let fullName: string = `Will`;
let obj = {};
obj.name = 'Will';
let arr = [];
arr.push({});
自動型別推導 (Type Inference)
An gu la r
User Group Taiwan
列舉範例
• http://www.typescriptlang.org/play/index.html
列舉型別 (Enum)
var Day;
(function (Day) {
Day[ Day["Sunday"] = 0 ] = "Sunday";
Day[ Day["Monday"] = 1 ] = "Monday";
Day[ Day["Tuesday"] = 2 ] = "Tuesday";
Day[ Day["Wednesday"] = 3 ] = "Wednesday";
Day[ Day["Thursday"] = 4 ] = "Thursday";
Day[ Day["Friday"] = 5 ] = "Friday";
Day[ Day["Saturday"] = 6 ] = "Saturday";
})(Day || (Day = {}));
var d = Day.Friday;
enum Day {
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
var d = Day.Friday;
An gu la r
User Group Taiwan
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
let a = document.getElementById('myLink'); // HTMLElement 型別
a.href = "http://blog.miniasp.com/"; // 找不到 href 屬性
let a = <HTMLAnchorElement>document.getElementById('myLink');
a.href = "http://blog.miniasp.com/"; // OK
型別轉換 (Type assertions)
An gu la r
User Group Taiwan
排除過度屬性檢查的型別宣告技巧
允許任意屬性的物件宣告
interface ILabel {
label: string; // 必要屬性,必須傳入!
[propName: string]: any; // 允許任意屬性傳入
}
function printLabel(labelledObj: ILabel) {
console.log(labelledObj.label);
}
printLabel({ label: "Size 10 Object", size: 10 });
An gu la r
User Group Taiwan
預設型別檢查模式 ( regular type checking mode )
• let a: T; // 可以指派給 undefined 或 null
// 因為 undefined 與 null 是所有型別的子型別
嚴格空值檢查模式 ( strict null checking mode ) ( --strictNullChecks )
• let a: T; // 不允許為 undefined 或 null (嚴格檢查)
• let a: T | null; // 不允許為 undefined 也代表要有初始值才能用
• let a: T | undefined;
• let a: T | undefined | null;
• 可選參數預設就擁有 undefined 型別,啟用嚴格空值檢查模式也一樣
type T1 = (x?: number) => string;
TypeScript 2.0 的嚴格空值檢查模式 (1)
An gu la r
User Group Taiwan
預設型別檢查模式 ( regular type checking mode )
• let a = null; // a 變數型別為 any
• let b = undefined; // b 變數型別為 any
嚴格空值檢查模式 ( strict null checking mode ) ( --strictNullChecks )
• let a = null; // a 變數型別為 null
• let b = undefined; // b 變數型別為 undefined
TypeScript 2.0 的嚴格空值檢查模式 (2)
An gu la r
User Group Taiwan
非空值斷言運算子 ( ! ) ( Non-null assertion operator )
TypeScript 2.0 的嚴格空值檢查模式 (3)
An gu la r
User Group Taiwan
傳統的聯合類型
• let a = number | string | undefined;
字串實字聯合類型 (String Literal Types)
• let b = "Will" | "John" | "Mary";
數值實字聯合類型 (Numeric Literal Types)
• function rollDie(): 1 | 2 | 3 | 4 | 5 | 6 { }
列舉成員聯合類型 (Enum Member Types)
• let kind: ShapeKind.Square | ShapeKind.Circle;
標記的聯合類型 ( 深度分析程式碼對型別的用法進而做出型別判斷 )
• https://github.com/Microsoft/TypeScript/wiki/What's-new-in-
TypeScript#tagged-union-types
標記的聯合類型 (Tagged union types)
An gu la r
User Group Taiwan
原始型別 never 用來宣告某個函式或變數永遠不可能有值
• let a: never = function test() { while (true) { } };
關於 void 型別的特性
• 宣告 void 型別的變數只能是 undefined 與 null ( 代表沒有值 )
• undefined 與 null 是所有型別的子型別 (subtype)
關於 never 型別的特性
• never 是所有型別的子型別 (subtype),所以不用特別宣告!
• 沒有任何型別是 never 的子型別 ( 除了 never 以外 )
• 若函式表達式或箭頭函式要能自動推導出 never 型別,有以下條件:
• 函式中沒有任何 return 敘述或回傳的只會有 never 型別
• 函式一定不能跑到函式最後一行 (end point of the function is not reachable)
TypeScript 2.0 推出的 never 原始型別
An gu la r
User Group Taiwan
TypeScript 1.x 以下的編譯器
• 預設函式內使用 this 預設型別為 any
TypeScript 2.0 編譯器新增 --noImplicitThis 旗標
• 在函式中預設無法使用型別為 any 的 this 變數!
• 如果要使用 this 必須在函式的第一個參數加入 this 的型別宣告
( 編譯之後的 JavaScript 會自動移除 this 參數 )
在函式中使用 this 的嚴格用法
An gu la r
User Group Taiwan
TypeScript 2.1 編譯器新增 --noImplicitAny 旗標
Untyped imports
• import { x } from "asdf";
• 匯入的模組如果沒有 declaration file,預設匯入的變數將會是 any 型別
• 如果啟用 --noImplicitAny 就會出現錯誤訊息
Improved any Inference
• let x; // implicitly 'any'
• let y = []; // implicitly 'any[]'
• let z: any; // explicitly 'any'
• 以前宣告完變數如果沒給型別宣告,預設就是隱含的 any 型別
• 如果啟用 --noImplicitAny 就會:
• 從第一次 assign 值的時候決定型別
• 如果執行的過程中修改了變數的值,型別也會動態轉換 (依然有編譯時期檢查)
Implicit any errors
• 有任何宣告出 any 型別的機會,就會立刻出現錯誤!
禁用隱含 any 型別功能
An gu la r
User Group Taiwan
TypeScript 2.1 編譯器新增 --alwaysStrict 旗標
啟用這個旗標會導致
• 所有的 TypeScript 程式碼都會以 strict mode 進行解析
• 所有輸出的 JavaScript 程式碼都會加上 "use strict"; 在每個 Scope
注意事項
• 所有相關模組都會自動進入嚴格編譯模式
• 建議用在 non-module 的程式碼
永遠採用嚴格編譯模式
An gu la r
User Group Taiwan
TypeScript 語言特性
An gu la r
User Group Taiwan
ES2017 Spread and Rest
• let copy = { ...original }; // shallow copy
• let merged = { ...foo, ...bar, ...baz }; // shallow copy
• let obj = { x: 1, y: "string" };
var newObj = {...obj, z: 3, y: 4};
// { x: number, y: number, z: number }
• let obj = { x: 1, y: 1, z: 1 };
let { z, ...obj1 } = obj;
obj1; // {x: number, y: number};
TypeScript 2.1 帶來 ES2017 的 … 功能
An gu la r
User Group Taiwan
TypeScript 2.1 讓 Async 函式支援到 ES3
An gu la r
User Group Taiwan
TypeScript - JavaScript that scales
What's new in TypeScript · Microsoft/TypeScript Wiki
TypeScript Handbook (中文版)
New in JavaScript - JavaScript | MDN
相關連結
An gu la r
User Group Taiwan
Thank you
An gu la r
User Group Taiwan
The Will Will Web
記載著 Will 在網路世界的學習心得與技術分享
• http://blog.miniasp.com/
Will 保哥的技術交流中心 (臉書粉絲專頁)
• http://www.facebook.com/will.fans
Will 保哥的噗浪
• http://www.plurk.com/willh/invite
Will 保哥的推特
• https://twitter.com/Will_Huang
聯絡資訊

TypeScript 綜合格鬥技

  • 1.
    An gu lar User Group Taiwan TypeScript 綜合格鬥技 多奇數位創意有限公司 技術總監 黃保翕 ( Will 保哥 ) 部落格:http://blog.miniasp.com/ Angular 線上讀書會 第 3 季
  • 2.
    An gu lar User Group Taiwan TypeScript 編譯器
  • 3.
    An gu lar User Group Taiwan 找出 TypeScript 編譯器的路徑與版本 若 PATH 環境變數有問題,使用 Rapid Environment Editor 可快速修復! npm list -g --depth=0 where tsc tsc -v
  • 4.
    An gu lar User Group Taiwan tsc --init 初始化 tsconfig.json 設定檔
  • 5.
    An gu lar User Group Taiwan 編譯所有檔案 (讀取 tsconfig.json 設定檔) (預設編譯含子目錄下的所有檔案) • tsc 編譯單一檔案 (需指定 TypeScript 編譯器選項) • tsc [options] [file ...] 顯示完整的 TypeScript 編譯器選項 • tsc --all 顯示 tsc 編譯器摘要說明 • tsc -h 編譯 TypeScript 程式
  • 6.
    An gu lar User Group Taiwan 問題說明 • ng new --minimal demo1 • code demo1 • 透過 VSCode 檔案總管將 src/environments 目錄移到 src/app/ 目錄下 • npm start Angular 下的 TypeScript 偵錯技巧 Allow to disable drag and drop in the files explorer #4842 ( "explorer.enableDragAndDrop": false )
  • 7.
    An gu lar User Group Taiwan Glob support in tsconfig.json • * 代表 0 個到多個字元比對 (不含目錄分隔字元) • ? 代表 1 個字元比對 (不含目錄分隔字元) • **/ 代表比對任意子目錄 設定 Base URL 預設 import 的基底路徑 設定 Path mapping • 必須搭配 "baseUrl" 設定一起使用 • Angular CLI 專案只能設定在根目錄的 tsconfig.json 設定檔中 tsconfig.json 設定技巧
  • 8.
    An gu lar User Group Taiwan 預設載入內建的模組定義檔 ( --lib ) es2015.core es2015.collection es2015.iterable es2015.promise es2015.proxy es2015.reflect es2015.generator es2015.symbol es2015.symbol.wellknown dom (Angular 5) webworker es5 es6 / es2015 es2016 es2016.array.include es2017 (Angular 5) es2017.object es2017.sharedmemory scripthost
  • 9.
    An gu lar User Group Taiwan TypeScript 型別應用
  • 10.
    An gu lar User Group Taiwan let decimal = 100; let isDone = false; let fullName: string = `Will`; let obj = {}; obj.name = 'Will'; let arr = []; arr.push({}); 自動型別推導 (Type Inference)
  • 11.
    An gu lar User Group Taiwan 列舉範例 • http://www.typescriptlang.org/play/index.html 列舉型別 (Enum) var Day; (function (Day) { Day[ Day["Sunday"] = 0 ] = "Sunday"; Day[ Day["Monday"] = 1 ] = "Monday"; Day[ Day["Tuesday"] = 2 ] = "Tuesday"; Day[ Day["Wednesday"] = 3 ] = "Wednesday"; Day[ Day["Thursday"] = 4 ] = "Thursday"; Day[ Day["Friday"] = 5 ] = "Friday"; Day[ Day["Saturday"] = 6 ] = "Saturday"; })(Day || (Day = {})); var d = Day.Friday; enum Day { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday } var d = Day.Friday;
  • 12.
    An gu lar User Group Taiwan let someValue: any = "this is a string"; let strLength: number = (<string>someValue).length; let someValue: any = "this is a string"; let strLength: number = (someValue as string).length; let a = document.getElementById('myLink'); // HTMLElement 型別 a.href = "http://blog.miniasp.com/"; // 找不到 href 屬性 let a = <HTMLAnchorElement>document.getElementById('myLink'); a.href = "http://blog.miniasp.com/"; // OK 型別轉換 (Type assertions)
  • 13.
    An gu lar User Group Taiwan 排除過度屬性檢查的型別宣告技巧 允許任意屬性的物件宣告 interface ILabel { label: string; // 必要屬性,必須傳入! [propName: string]: any; // 允許任意屬性傳入 } function printLabel(labelledObj: ILabel) { console.log(labelledObj.label); } printLabel({ label: "Size 10 Object", size: 10 });
  • 14.
    An gu lar User Group Taiwan 預設型別檢查模式 ( regular type checking mode ) • let a: T; // 可以指派給 undefined 或 null // 因為 undefined 與 null 是所有型別的子型別 嚴格空值檢查模式 ( strict null checking mode ) ( --strictNullChecks ) • let a: T; // 不允許為 undefined 或 null (嚴格檢查) • let a: T | null; // 不允許為 undefined 也代表要有初始值才能用 • let a: T | undefined; • let a: T | undefined | null; • 可選參數預設就擁有 undefined 型別,啟用嚴格空值檢查模式也一樣 type T1 = (x?: number) => string; TypeScript 2.0 的嚴格空值檢查模式 (1)
  • 15.
    An gu lar User Group Taiwan 預設型別檢查模式 ( regular type checking mode ) • let a = null; // a 變數型別為 any • let b = undefined; // b 變數型別為 any 嚴格空值檢查模式 ( strict null checking mode ) ( --strictNullChecks ) • let a = null; // a 變數型別為 null • let b = undefined; // b 變數型別為 undefined TypeScript 2.0 的嚴格空值檢查模式 (2)
  • 16.
    An gu lar User Group Taiwan 非空值斷言運算子 ( ! ) ( Non-null assertion operator ) TypeScript 2.0 的嚴格空值檢查模式 (3)
  • 17.
    An gu lar User Group Taiwan 傳統的聯合類型 • let a = number | string | undefined; 字串實字聯合類型 (String Literal Types) • let b = "Will" | "John" | "Mary"; 數值實字聯合類型 (Numeric Literal Types) • function rollDie(): 1 | 2 | 3 | 4 | 5 | 6 { } 列舉成員聯合類型 (Enum Member Types) • let kind: ShapeKind.Square | ShapeKind.Circle; 標記的聯合類型 ( 深度分析程式碼對型別的用法進而做出型別判斷 ) • https://github.com/Microsoft/TypeScript/wiki/What's-new-in- TypeScript#tagged-union-types 標記的聯合類型 (Tagged union types)
  • 18.
    An gu lar User Group Taiwan 原始型別 never 用來宣告某個函式或變數永遠不可能有值 • let a: never = function test() { while (true) { } }; 關於 void 型別的特性 • 宣告 void 型別的變數只能是 undefined 與 null ( 代表沒有值 ) • undefined 與 null 是所有型別的子型別 (subtype) 關於 never 型別的特性 • never 是所有型別的子型別 (subtype),所以不用特別宣告! • 沒有任何型別是 never 的子型別 ( 除了 never 以外 ) • 若函式表達式或箭頭函式要能自動推導出 never 型別,有以下條件: • 函式中沒有任何 return 敘述或回傳的只會有 never 型別 • 函式一定不能跑到函式最後一行 (end point of the function is not reachable) TypeScript 2.0 推出的 never 原始型別
  • 19.
    An gu lar User Group Taiwan TypeScript 1.x 以下的編譯器 • 預設函式內使用 this 預設型別為 any TypeScript 2.0 編譯器新增 --noImplicitThis 旗標 • 在函式中預設無法使用型別為 any 的 this 變數! • 如果要使用 this 必須在函式的第一個參數加入 this 的型別宣告 ( 編譯之後的 JavaScript 會自動移除 this 參數 ) 在函式中使用 this 的嚴格用法
  • 20.
    An gu lar User Group Taiwan TypeScript 2.1 編譯器新增 --noImplicitAny 旗標 Untyped imports • import { x } from "asdf"; • 匯入的模組如果沒有 declaration file,預設匯入的變數將會是 any 型別 • 如果啟用 --noImplicitAny 就會出現錯誤訊息 Improved any Inference • let x; // implicitly 'any' • let y = []; // implicitly 'any[]' • let z: any; // explicitly 'any' • 以前宣告完變數如果沒給型別宣告,預設就是隱含的 any 型別 • 如果啟用 --noImplicitAny 就會: • 從第一次 assign 值的時候決定型別 • 如果執行的過程中修改了變數的值,型別也會動態轉換 (依然有編譯時期檢查) Implicit any errors • 有任何宣告出 any 型別的機會,就會立刻出現錯誤! 禁用隱含 any 型別功能
  • 21.
    An gu lar User Group Taiwan TypeScript 2.1 編譯器新增 --alwaysStrict 旗標 啟用這個旗標會導致 • 所有的 TypeScript 程式碼都會以 strict mode 進行解析 • 所有輸出的 JavaScript 程式碼都會加上 "use strict"; 在每個 Scope 注意事項 • 所有相關模組都會自動進入嚴格編譯模式 • 建議用在 non-module 的程式碼 永遠採用嚴格編譯模式
  • 22.
    An gu lar User Group Taiwan TypeScript 語言特性
  • 23.
    An gu lar User Group Taiwan ES2017 Spread and Rest • let copy = { ...original }; // shallow copy • let merged = { ...foo, ...bar, ...baz }; // shallow copy • let obj = { x: 1, y: "string" }; var newObj = {...obj, z: 3, y: 4}; // { x: number, y: number, z: number } • let obj = { x: 1, y: 1, z: 1 }; let { z, ...obj1 } = obj; obj1; // {x: number, y: number}; TypeScript 2.1 帶來 ES2017 的 … 功能
  • 24.
    An gu lar User Group Taiwan TypeScript 2.1 讓 Async 函式支援到 ES3
  • 25.
    An gu lar User Group Taiwan TypeScript - JavaScript that scales What's new in TypeScript · Microsoft/TypeScript Wiki TypeScript Handbook (中文版) New in JavaScript - JavaScript | MDN 相關連結
  • 26.
    An gu lar User Group Taiwan Thank you
  • 27.
    An gu lar User Group Taiwan The Will Will Web 記載著 Will 在網路世界的學習心得與技術分享 • http://blog.miniasp.com/ Will 保哥的技術交流中心 (臉書粉絲專頁) • http://www.facebook.com/will.fans Will 保哥的噗浪 • http://www.plurk.com/willh/invite Will 保哥的推特 • https://twitter.com/Will_Huang 聯絡資訊

Editor's Notes

  • #9 tsc --target es5 --lib es5,es2015.promise "compilerOptions": { "lib": ["es5", "es2015.promise"] }
  • #17 // Compiled with --strictNullChecks interface Entity { name: string; } function validateEntity(e?: Entity) { // Throw exception if e is null or invalid entity } function processEntity(e?: Entity) { validateEntity(e); let s = e!.name; // Assert that e is non-null and access name }
  • #25 function delay(milliseconds: number) { return new Promise<void>(resolve => { setTimeout(resolve, milliseconds); }); } async function dramaticWelcome() { console.log("Hello"); for (let i = 0; i < 3; i++) { await delay(500); console.log("."); } console.log("World!"); } dramaticWelcome();