知乎html
我的博客node
Githubreact
最近入職,發現公司使用到typescript,因此就在此留下一個筆記,方便本身和你們一塊兒學習。git
TypeScript是一種由微軟開發的自由和開源的編程語言。它是JavaScript的一個嚴格超集,並添加了可選的靜態類型和基於類的面向對象編程。es6
你們平常學習能夠去TS Playground測試一些代碼github
那咱們就來開始學習吧!正則表達式
在使用TS以前,咱們定義的JavaScript變量都是弱類型語言,它不像C,Java這種,會在編譯的時候對變量進行類型檢查,因此有的時候會出現意想不到的Bug。typescript
使用TS咱們能夠處理很簡單的數據類型:編程
// boolean let isEmpty: boolean = true; // Type '"false"' is not assignable to type 'boolean'. isEmpty = 'false'; isEmpty = false;
// number let num: number = 10; // Type '"1"' is not assignable to type 'number'. num = '1'; num = 1;
// string let github_name: string; github_name = 120; github_name = 'Rain120';
// array let arr: number[]; arr = [1, '2', 3]; arr = [1, 2, 3]; let arr1: Array<number>; arr1 = [1, '2', 3]; arr1 = [1, 2, 3]; let fe: string[]; fe = [1, 2, 3]; // TS fe = ['Vue', 'React', 'Angular'];
// any let type_con: any; type_con = []; type_con = {}; type_con = 1; type_con = '2'; type_con = true; type_con.func();
//void let test_void: void = null; test_void = 1;
function vo(): void { console.log('這是一個返回值爲void的函數'); } function vo1(): void { console.log('這是一個返回值爲void的函數'); return ''; } function str(): string { console.log('這是一個返回值爲string的函數'); } function str1(): string { console.log('這是一個返回值爲string的函數'); return 'string'; }
當咱們在使用函數的時候,有些時候會使用到函數參數默認,或者可選參數,那麼在TS中如何寫呢?json
function game(name: string, rank?: string, score: number = 0): string { return `${name} ${rank} ${score}` } console.log(game('rainy', 'difficult', 10000)); console.log(game('rainy', 'difficult')); console.log(game('rainy'));
class Person { name: string; constructor(name: string) { this.name = name; } greet() { console.log(`Hello, ${this.name}`); } } class Student extends Person { name: string; age: number; constructor(name: string, age: number) { super(name); this.age = age; } greet() { console.log(`Hello, My name is ${this.name} and I'm ${this.age}`); } study() { console.log(`${this.name}, you should go to study.`) } } let p = new Person('Rain120'); console.log('p:', p.name) p.greet() let stu = new Student('Rain', 21); console.log('stu:', stu.name, stu.age); stu.greet(); stu.study();
咱們在學習面向對象的語言,C++和Java時候知道類的屬性和方法是有修飾符的,他們決定了外部是否可以訪問類中的屬性、方法,當用戶爲定義是,屬性和方法默認都是public 屬性,其中還有protected 和private 屬性。當你使用private 修飾符定義成屬性或者方法時,若是你須要讓其餘使用者使用這個屬性時,你能夠定義一個public 的方法,以後用戶只能經過這個API接口來獲取屬性值或者方法的結果,例如:
class Person { private name: string; constructor(name: string) { this.name = name; } getName() { return this.name; } } let p = new Person('Rain120'); console.log('person name:', p.name) console.log('person name:', p.getName())
雖然這裏報錯了,可是編譯結果倒是能夠的應爲TS在轉換成JS語言後,並無真的將name編譯成私有的屬性,TypeScript的核心原則之一是對值所具備的結構進行類型檢查,它的做用只是提示開發者。
protected 修飾符與private 修飾符的行爲很類似,但有一點不一樣,protected 成員在派生類中仍然能夠訪問, 這就不詳細講解這些了,你們能夠去學習下Java或者C++的類,感覺一下。
在TypeScript裏,接口的做用就是爲這些類型命名和爲你的代碼或第三方代碼定義契約。這句話太官方了,我本身理解的就是它定義了一些你本身約定的參數類型。
工做中,咱們使用到的是React+Typescript,因此,我把我平常寫法拿出來。
interface SystemsProps { systems: any } export class Systems extends React.Component<SystemsProps, any> ... render() { const { systems } = this.props return ( <div>{systems.name}</div> ) } }
固然,從C++中學到接口也是能夠繼承的,例如:
interface Color{ color: string; } interface Car extends Color{ price: number; } let car = <Car>{}; car.color = "white"; car.price = 10000000;
在像C++和Java這樣的語言中,可使用泛型來建立可重用的組件,一個組件能夠支持多種類型的數據。 這樣用戶就能夠以本身的數據類型來使用組件。
其實咱們以前有用到泛型,只是沒有說到這個概念。
let arr: Array<number> = [1, 2, 3, 4];
這是一個最簡答你的泛型,定義了一個number類型的數組,下面我寫一個複雜點的泛型:
class Fruit { name: string; price: number; constructor(name: string, price: number) { this.name = name; this.price = price; } sold() { console.log(`${this.name} sold $${this.price}`) } } let fruit: Array<Fruit> = [] fruit[0] = new Fruit('apple', 8) fruit[1] = new Fruit('banana', 5) fruit[2] = new Fruit('lemon', 10) console.log(fruit)
這個泛型是一個Fruit類型的數組,這個數組的子元素全是Fruit類型,當咱們定義一個其餘類型是,例如
fruit[3] = { name: 'watermelon', price: 2 }
let num = 10; num = 'str';
咱們日常在使用變量賦值的時候,這樣寫是沒有問題,可是使用TS類型檢查後,它會根據用戶第一次定義或者賦值的類型來推斷該變量的類型,這就是TS的類型推斷機制。
這裏咱們講下咱們常見的幾種的迭代器,包括for-in, for-of,用來跟forEach對比,直接上代碼,咱們從代碼來分析它們之間的不一樣
let arr: any = ['a','b','c']; arr.type = 'array' arr.forEach((item, index) => { console.log('forEach', index, item, arr[index]); }) for (let i in arr) { console.log('for-in', i, arr[i]); } let obj = { 'a': 'I\'m a', 'b': 'I\'m b', 'c': 'I\'m c' } for (let i of arr) { console.log('for-of', i, obj[i]); }
從結果上來看,
forEach:只是常見的for循環,它不會遍歷該對象的屬性值;
for-in:迭代的是對象的鍵(key)的列表,它會遍歷對象的屬性;
for-of:迭代對象的鍵對應的值(value),它也不會遍歷對象的屬性。
這個地方熟悉CommonJS的都會知道export(導出), import(導入),因此這裏就不詳細講了,直接跳過
最後講一下,tsconfig.json的配置,詳見tsconfig.json
{ "compilerOptions": { "moduleResolution": "node", "outDir": ./dist", // 生成的全部文件放在dist目錄下 "target": "es5", // 將JavaScript代碼降級到低版本ECMAScript 5 "lib": ["es6", "dom"], "rootDir": "app/", //僅用來控制輸出的目錄結構。 "jsx": "react", // 用於指定按照何種方式生成jsx代碼,可選react和preserve。 "module": "esnext", // 用於指定模塊的代碼生成規則,可使用 commonjs 、 amd 、 umd 、 system 、 es6 、 es2015 、 none 這些選項。 "declaration": false, // 是否須要生成定義文件d.ts,設置爲true,則生成 "allowJs": true, // 接受JavaScript作爲輸入 "allowSyntheticDefaultImports": true, // 置爲true時,則容許從沒有默認導出的模塊中默認導入(也就是不作檢查)。 "inlineSourceMap": false, // 是否須要將sourceMap文件生成到js文件中,設置爲true,則生成到js文件中。 "sourceMap": true, // 把 ts 文件編譯成 js 文件的時候,同時生成對應的 map 文件 "noEmitOnError": false, // 設置爲true時,若是遇到了錯誤,就再也不輸出 "emitDecoratorMetadata": false, // 設置爲true,則使用元數據特性 "experimentalDecorators": true, // 設置爲true,則支持ES7的裝飾器特性 "noImplicitReturns": true, // 會防止你忘記在函數末尾返回值 "noImplicitThis": false, "noImplicitUseStrict": false, // 當設置爲true時,編譯輸出時不會調用'use strict'指令(也就是不生成use strict) "noImplicitAny": false, // 若是編譯器沒法根據變量的用途推斷出變量的類型,它就會悄悄的把變量類型默認爲 any。 "noUnusedLocals": false, "baseUrl": "app", "paths": { "app": ["app"] } }, // 包括app下的全部.ts(對應js文件), .tsx(對應jsx文件)文件 "include": [ "app/**/*.ts", "app/**/*.tsx" ], // 忽略node_modules下全部的文件 "exclude": [ "node_modules", ... //其餘要忽略的文件或者正則表達式表示 ] }