ts的優(yōu)點:靜態(tài)編譯提示錯誤狐赡,強類型撞鹉,接口和繼承,是js的超集颖侄,需要編譯后執(zhí)行
編譯
1鸟雏、ts后綴建立文件后通過tsc進行指定文件的編譯,不帶任何輸入文件的情況下調(diào)用tsc览祖,編譯器會從當前目錄開始去查找tsconfig.json文件孝鹊,逐級向上搜索父目錄。
2展蒂、不帶任何輸入文件的情況下調(diào)用tsc又活,且使用命令行參數(shù)--project(或-p)指定一個包含tsconfig.json文件的目錄。
3锰悼、當命令行上指定了輸入文件時柳骄,tsconfig.json文件會被忽略。
4松捉、直接通過ts test.ts會生成對應(yīng)的js文件
5夹界、通過sudo npm install ts-node -g --save --unsafe-perm=true --allow-root安裝依賴 可通過ts-node test.ts直接執(zhí)行
6馆里、通過配置vscode實現(xiàn)執(zhí)行tsc --init 生成文件 tsconfig.json隘世,修改路徑和添加watch監(jiān)聽實現(xiàn)自動監(jiān)控ts文件生成js: https://www.cnblogs.com/liangyy/p/12436720.html
tsconfig.json配置文件
配置示例
{
"extends": "./configs/base",
"compilerOptions": {
"module": "commonjs",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true,
"types" : ["node", "lodash", "express"],
"typeRoots" : ["./typings"]
},
"files": [
"core.ts",
"sys.ts",
"types.ts"
],
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
- extends 拓展配置文件 引入的會覆蓋當前的源文件配置
- 默認配置下會編譯當前目錄以及子目錄下的所有文件 排除可能是輸出文件 支持拓展名為ts tsx d.ts 當allowJs設(shè)置為true則包含js jsx拓展名
- 當配置了files之后只會引入對應(yīng)的配置下的文件,優(yōu)先于exclude指定的排除文件
- include和exclude指定匹配模式鸠踪,支持(匹配0+多個字符不包含目錄)? (匹配一個任意字符)*/ (遞歸匹配任意子目錄)
- 默認所有可見的@types包都會在編譯時包含進來丙者,node_modules/@types文件夾下以及子文件下所有包都是可見的,當被置頂了typeRoots則只有被指定的包會被包含進來营密,指定了types則node_modules/@types下的這些包會被引入進來械媒,可以通過指定types:[]來禁用自動引入
基礎(chǔ)語法
1、number boolean string null undefined指定五種基本類型,void指定空值可以賦值為null undefined纷捞,反之void不可賦值給任何類型痢虹;any代表任意類型的值(類似不寫);類型推論主儡,當你定義變量的時候賦值奖唯,ts會根據(jù)你的賦值推出一個類型,不進行賦值則會默認為任意值糜值;聯(lián)合類型:通過|分隔多個類型丰捷,訪問屬性/方法時只能是共有的,當賦值后則會類型推斷
2寂汇、接口:通過interface關(guān)鍵字進行定義病往,?可選屬性、[propName: type] 自定義屬性(自定義屬性后骄瓣,其他屬性必須為自定義屬性的子類)停巷、readonly只讀屬性
- 接口描述了ts種復雜的類型結(jié)構(gòu),接口繼承自類的時候繼承了它的成員但是沒有繼承實現(xiàn)榕栏,所以接口的功能只能由子類來實現(xiàn)叠穆。
3、數(shù)組類型number[]或者Array<number>臼膏;也可以通過接口定義(復雜)硼被,其他類數(shù)組類型有自己的類型定義如IArguments NodeList
4、函數(shù)有兩種定義方式渗磅,通過?進行可選參數(shù)定義嚷硫,只能寫在最后,如果是寫了默認值的參數(shù)始鱼,ts認為是可選參數(shù)仔掸,且無位置要求,通過解構(gòu)獲取剩余參數(shù)医清,也可進行定義
5起暮、斷言 as語法:只要A兼容B或者B兼容A,就可以互相斷言会烙,子類可以被斷言為一個父類负懦,父類斷言可以為子類,是因為子類包含父類的所有屬性柏腻,可以訪問到父類的內(nèi)容
6纸厉、聲明文件一種是放在源碼里,通過types指定文件目錄五嫂;一種是補充到type庫颗品,最后是自己實現(xiàn).d.ts文件
7肯尺、type指定類型別名,類型約束
8躯枢、元組则吟,賦值時需要匹配,可單獨賦值锄蹂,可越界為聯(lián)合類型
9逾滥、enum 枚舉類型可以手動覆蓋;可以包含計算值败匹,下一個加一寨昙; 常數(shù)枚舉類型不可計算,外部枚舉類型 declare
10掀亩、類:public private protected abstract舔哪,抽象類必須被子類實現(xiàn)
11垦搬、接口繼承類:ts中的類在聲明時同時創(chuàng)建了一個同名的類型渔肩,它包含了屬性和方法,沒有constructor和static屬性卫键,接口繼承時繼承了這部分類型炼七,類似繼承了類生成的實例
類 接口 函數(shù)的用法
1缆巧、類 跟es6中的類差不多,添加了修飾符:public protected private豌拙,以及readonly陕悬;如果是抽象類abstract則不能直接實例化,抽象類中的抽象屬性和方法必須被子類實現(xiàn)按傅,類和接口很像捉超,他們的區(qū)別在于:
- 類通過class實現(xiàn),通過extends繼承被子類繼承唯绍;接口是通過interface定義拼岳,被類所實現(xiàn)
- 類的方法可以自己實現(xiàn),抽象類子類必須實現(xiàn)况芒;接口則是一組規(guī)則的定義
- 類通常是對一個類別的公共部分做抽象惜纸,有規(guī)律;接口只是抽象绝骚,可能并無關(guān)聯(lián)
2耐版、接口:接口中可以定義可選屬性,索引屬性皮壁,只讀屬性椭更;也支持定義函數(shù)以及構(gòu)造函數(shù)的類型
- 函數(shù)重載 根據(jù)不同的參數(shù)個數(shù)指定不同的類型
- this指向 由于運行時才能確定this指向哪审,在ts中可以進行手動的this指向
3蛾魄、泛型 通過T來代指當運行時才能確認的類型,難點在于結(jié)合keyof和T<k>使用
4、兼容 如A=B滴须,協(xié)變是B包含A舌狗,逆變是A包含B,雙向協(xié)變是沒有規(guī)則
對象扔水、函數(shù)返回值痛侍、類中采用的是協(xié)變
函數(shù)參數(shù)個數(shù)的兼容采用的是逆變
函數(shù)參數(shù)的兼容和泛型用的是雙向協(xié)變
- 函數(shù)參數(shù)和返回值的類型:https://jkchao.github.io/typescript-book-chinese/tips/covarianceAndContravariance.html#%E4%B8%80%E4%B8%AA%E6%9C%89%E8%B6%A3%E7%9A%84%E9%97%AE%E9%A2%98
總結(jié):(Animal → Greyhound) 可以正確傳入 (Dog → Dog) , 說明返回值是協(xié)變的魔市,參數(shù)是逆變的主届。
function greeter(person:string) {
return "Hello, " + person;
}
let user = ["Jane User"];
// document.body.innerHTML = greeter();
let u: void
// let num: number = u
let anyThind: any = 'hello'
console.log(anyThind.myName)
let from: string|number
from.toString()
from.length
from = 'z'
from.length
interface Person {
name: string
age: number
}
let child:Person = {
name: 'zz',
age: 12
}
interface Person {
readonly id:number
name: string
age?:number
[propName: string]: string|number
}
let child1: Person = {
id:1,
name: 'z',
class: 1
}
child1.id = 2
// 數(shù)組
let list: number[] = [1]
let list2: Array<number> = [2]
interface IList {
[index:number]: number,
length:number,
callee: Function
}
function sum() {
let args: IList = arguments
}
// 函數(shù)
function myName(x:number,y:number, ...items: any[]): number {
return x+y
}
let mySum: (x:number, y:number) => number = function(x:number, y:number):number {return x+y}
// 函數(shù)重載
function reverse(x:number): number
function reverse(x:string): string
function reverse(x: string|number): number| string {
return x
}
// 斷言和聲明
interface Animal {
name: string
}
interface Cat {
name: string,
voice: string
}
let animal:Animal = {
name: 'tom'
}
// 斷言只需要有互相包含的關(guān)系
let bai = animal as Cat
// 賦值必須滿足前者兼容后者
let baige2:Cat = {
name: 'baige',
voice: 'miao'
}
let baige:Cat = animal //失敗
// 類型別名
type stringName = string
let names: stringName = 'owo'
// 類型約束
type EventNames = 'click' | 'scroll' | 'mousemove'
// 元組
let tom: [string, number]
tom[0]='first'
tom = ['second',0]
tom.push(3)
// 枚舉
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat}
// 類
abstract class Animals {
public name;
public constructor(name) {
this.name = name
}
public abstract voice()
}
class Cats extends Animals {
public voice() {
// 必須要實現(xiàn)抽象類的屬性
}
}
let miao = new Cats('bai')
// 泛型 后置確定類型 可定義約束
function copyFields<T extends U, U>(target: T, source: U): T {
for(let id in source) {
target[id] = (<T>source)[id]
}
return target
}
let x = {a:1, b:2}
let y = {b:10}
copyFields(x, y)