ts是js的超集,運行ts需要安裝ts運行環境
使用npm工具安裝:
npm install -g typescript
ts文件通過tsc編譯爲js代碼,tsc Test.ts,之後可通過node命令執行該js代碼
ts中;是可選的,加上比較好
ts是一種oop語言
1.數據類型
any:表示任意類型
number:64位雙精度浮點值
string:字符串
boolean
array:數組 []
元組:元素類型可以不同的數組
enum:枚舉
void/null/undefined/never
2.變量聲明與作用域
ts對變量聲明作了更加精確的限制
有四種方式聲明變量
聲明變量的類型及初始值:
var [變量名] : [類型] = 值;
聲明變量的類型及但沒有初始值,變量值會設置爲 undefined:
var [變量名] : [類型];
聲明變量並初始值,但不設置類型類型,該變量可以是任意類型:
var [變量名] = 值;
聲明變量沒有設置類型和初始值,類型可以是任意類型,默認初始值爲 undefined:
var [變量名];
TypeScript 遵循強類型,如果將不同的類型賦值給變量會編譯錯誤
var num:number = "hello" // 這個代碼會編譯錯誤
類型斷言(Type Assertion)
類型斷言可以用來手動指定一個值的類型,即允許變量從一種類型更改爲另一種類型。
語法格式:
<類型>值
或:
值 as 類型
實例
- var str = '1'
- var str2:number = <number> <any> str //先將str變爲任意類型any,再轉換爲number
關鍵字let:聲明局部變量
關鍵字const:聲明一個只讀常量(final)
聯合類型(Union Types)
聯合類型(Union Types)表示取值可以爲多種類型中的一種。
聯合類型使用 |
分隔每個類型。
這裏的 let myFavoriteNumber: string | number
的含義是,允許 myFavoriteNumber
的類型是 string
或者 number
,但是不能是其他類型。
3.函數
ts新增一種函數聲明方式
function function_name(param1 [:datatype], param2 [:datatype]):return_type {
// 語句
return value;
}
可選參數:
TypeScript 函數裏,如果我們定義了參數,則我們必須傳入這些參數,除非將這些參數設置爲可選,可選參數使用問號標識 ?
function function_name(param1 [:datatype], param2? [:datatype]):return_type { // 語句 return value; }
默認參數:
我們也可以設置參數的默認值,這樣在調用函數的時候,如果不傳入該參數的值,則使用默認參數,語法格式爲:
function function_name(param1[:type],param2[:type] = default_value) {
}
注意:參數不能同時設置爲可選和默認。
剩餘參數:
有一種情況,我們不知道要向函數傳入多少個參數,這時候我們就可以使用剩餘參數來定義。
剩餘參數語法允許我們將一個不確定數量的參數作爲一個數組傳入。
函數的最後一個命名參數 restOfName 以 ... 爲前綴,它將成爲一個由剩餘參數組成的數組(剩餘參數數組)。
lambda,箭頭函數
Lambda 函數也稱之爲箭頭函數。
箭頭函數表達式的語法比函數表達式更短。
函數只有一行語句:
( [param1, parma2,…param n] )=>statement;
以下實例聲明瞭 lambda 表達式函數,函數返回兩個數的和:
var foo = (x:number)=>10 + x console.log(foo(100)) //輸出結果爲 110
ts支持函數重載,只需限定相同函數名的返回類型不同即可
4.接口
這裏的接口比較奇怪,與java中的不太一樣
TypeScript 中的接口是一個非常靈活的概念,除了可用於對類的一部分行爲進行抽象以外,也常用於對「對象的形狀(Shape)」進行描述。
簡單的例子
- interface Person {
- name: string;
- age: number;
- }
- let tom: Person = {
- name: 'Tom',
- age: 25
- };
上面的例子中,我們定義了一個接口 Person
,接着定義了一個變量 tom
,它的類型是 Person
。這樣,我們就約束了 tom
的形狀必須和接口 Person
一致。
接口一般首字母大寫。有的編程語言中會建議接口的名稱加上 I
前綴。
定義的變量比接口少了一些屬性是不允許的:
- interface Person {
- name: string;
- age: number;
- }
- let tom: Person = {
- name: 'Tom'
- };
- // index.ts(6,5): error TS2322: Type '{ name: string; }' is not assignable to type 'Person'.
- // Property 'age' is missing in type '{ name: string; }'.
多一些屬性也是不允許的:
- interface Person {
- name: string;
- age: number;
- }
- let tom: Person = {
- name: 'Tom',
- age: 25,
- gender: 'male'
- };
- // index.ts(9,5): error TS2322: Type '{ name: string; age: number; gender: string; }' is not assignable to type 'Person'.
- // Object literal may only specify known properties, and 'gender' does not exist in type 'Person'.
可見,賦值的時候,變量的形狀必須和接口的形狀保持一致。
可選屬性
有時我們希望不要完全匹配一個形狀,那麼可以用可選屬性:
- interface Person {
- name: string;
- age?: number;
- }
- let tom: Person = {
- name: 'Tom'
- };
- interface Person {
- name: string;
- age?: number;
- }
- let tom: Person = {
- name: 'Tom',
- age: 25
- };
可選屬性的含義是該屬性可以不存在。
這時仍然不允許添加未定義的屬性:
- interface Person {
- name: string;
- age?: number;
- }
- let tom: Person = {
- name: 'Tom',
- age: 25,
- gender: 'male'
- };
- // examples/playground/index.ts(9,5): error TS2322: Type '{ name: string; age: number; gender: string; }' is not assignable to type 'Person'.
- // Object literal may only specify known properties, and 'gender' does not exist in type 'Person'.
-
任意屬性
有時候我們希望一個接口允許有任意的屬性,可以使用如下方式:
- interface Person {
- name: string;
- age?: number;
- [propName: string]: any;
- }
- let tom: Person = {
- name: 'Tom',
- gender: 'male'
- };
使用 [propName: string]
定義了任意屬性取 string
類型的值。
需要注意的是,一旦定義了任意屬性,那麼確定屬性和可選屬性的類型都必須是它的類型的子集:
- interface Person {
- name: string;
- age?: number;
- [propName: string]: string;
- }
- let tom: Person = {
- name: 'Tom',
- age: 25,
- gender: 'male'
- };
- // index.ts(3,5): error TS2411: Property 'age' of type 'number' is not assignable to string index type 'string'.
- // index.ts(7,5): error TS2322: Type '{ [x: string]: string | number; name: string; age: number; gender: string; }' is not assignable to type 'Person'.
- // Index signatures are incompatible.
- // Type 'string | number' is not assignable to type 'string'.
- // Type 'number' is not assignable to type 'string'.
上例中,任意屬性的值允許是 string
,但是可選屬性 age
的值卻是 number
,number
不是 string
的子屬性,所以報錯了。
另外,在報錯信息中可以看出,此時 { name: 'Tom', age: 25, gender: 'male' }
的類型被推斷成了 { [x: string]: string | number; name: string; age: number; gender: string; }
,這是聯合類型和接口的結合。
只讀屬性
有時候我們希望對象中的一些字段只能在創建的時候被賦值,那麼可以用 readonly
定義只讀屬性:
- interface Person {
- readonly id: number;
- name: string;
- age?: number;
- [propName: string]: any;
- }
- let tom: Person = {
- id: 89757,
- name: 'Tom',
- gender: 'male'
- };
- tom.id = 9527;
- // index.ts(14,5): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property.
- 上例中,使用
readonly
定義的屬性id
初始化後,又被賦值了,所以報錯了。
注意,只讀的約束存在於第一次給對象賦值的時候,而不是第一次給只讀屬性賦值的時候:
- interface Person {
- readonly id: number;
- name: string;
- age?: number;
- [propName: string]: any;
- }
- let tom: Person = {
- name: 'Tom',
- gender: 'male'
- };
- tom.id = 89757;
- // index.ts(8,5): error TS2322: Type '{ name: string; gender: string; }' is not assignable to type 'Person'.
- // Property 'id' is missing in type '{ name: string; gender: string; }'.
- // index.ts(13,5): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property.
- 上例中,報錯信息有兩處,第一處是在對
tom
進行賦值的時候,沒有給id
賦值。
第二處是在給 tom.id
賦值的時候,由於它是隻讀屬性,所以報錯了。
接口可使用extneds關鍵字進行繼承
5.數組
最簡單的方法是使用「類型 + 方括號」來表示數組:
let fibonacci: number[] = [1, 1, 2, 3, 5];
6.類
使用class關鍵字進行聲明
構造方法使用constructor(參數){}進行聲明
內置方法:方法名():返回類型
聲明對象var 變量名=new 類名(參數)
類也可以通過extends關鍵字進行繼承,只能繼承一個類
關鍵字super代表父類
關鍵字static聲明靜態方法/字段
關鍵字instanceof:A instanceof B 判斷A是否是B的實例
三種訪問修飾符:public,protected,private
關鍵字implements表示實現接口
7.對象
與js中的一樣,對象就是變量key和值value的集合,key是變量名,value是任意類型的值
8.命名空間
關鍵字namespace用於聲明一個命名空間,命名空間內的類和對象需要被導出的使用關鍵字export進行聲明,同理,要引用其他的ts文件要在首部進行聲明
- namespace SomeNameSpaceName {
- export interface ISomeInterfaceName { }
- export class SomeClassName { }
- }
- namespace Drawing {
- export interface IShape {
- draw();
- }
- }
- /// <reference path = "IShape.ts" />
- namespace Drawing {
- export class Circle implements IShape {
- public draw() {
- console.log("Circle is drawn");
- }
- }
- }
9.模塊
TypeScript 模塊的設計理念是可以更換的組織代碼。
模塊是在其自身的作用域裏執行,並不是在全局作用域,這意味着定義在模塊裏面的變量、函數和類等在模塊外部是不可見的,除非明確地使用 export 導出它們。類似地,我們必須通過 import 導入其他模塊導出的變量、函數、類等。
兩個模塊之間的關係是通過在文件級別上使用 import 和 export 建立的。
模塊使用模塊加載器去導入其它的模塊。 在運行時,模塊加載器的作用是在執行此模塊代碼前去查找並執行這個模塊的所有依賴。 大家最熟知的JavaScript模塊加載器是服務於 Node.js 的 CommonJS 和服務於 Web 應用的 Require.js。
此外還有有 SystemJs 和 Webpack。
模塊導出使用關鍵字 export 關鍵字,語法格式如下:
// 文件名 : SomeInterface.ts export interface SomeInterface { // 代碼部分 }
要在另外一個文件使用該模塊就需要使用 import 關鍵字來導入:
import someInterfaceRef = require("./SomeInterface");