ts的優(yōu)點(diǎn):靜態(tài)編譯提示錯(cuò)誤,強(qiáng)類型,接口和繼承,是js的超集,需要編譯后執(zhí)行
編譯
1、ts后綴建立文件后通過(guò)tsc進(jìn)行指定文件的編譯,不帶任何輸入文件的情況下調(diào)用tsc,編譯器會(huì)從當(dāng)前目錄開始去查找tsconfig.json文件,逐級(jí)向上搜索父目錄。
2、不帶任何輸入文件的情況下調(diào)用tsc,且使用命令行參數(shù)--project(或-p)指定一個(gè)包含tsconfig.json文件的目錄。
3、當(dāng)命令行上指定了輸入文件時(shí),tsconfig.json文件會(huì)被忽略。
4、直接通過(guò)ts test.ts會(huì)生成對(duì)應(yīng)的js文件
5、通過(guò)sudo npm install ts-node -g --save --unsafe-perm=true --allow-root安裝依賴 可通過(guò)ts-node test.ts直接執(zhí)行
6、通過(guò)配置vscode實(shí)現(xiàn)執(zhí)行tsc --init 生成文件 tsconfig.json,修改路徑和添加watch監(jiān)聽實(shí)現(xiàn)自動(dòng)監(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 拓展配置文件 引入的會(huì)覆蓋當(dāng)前的源文件配置
- 默認(rèn)配置下會(huì)編譯當(dāng)前目錄以及子目錄下的所有文件 排除可能是輸出文件 支持拓展名為ts tsx d.ts 當(dāng)allowJs設(shè)置為true則包含js jsx拓展名
- 當(dāng)配置了files之后只會(huì)引入對(duì)應(yīng)的配置下的文件,優(yōu)先于exclude指定的排除文件
- include和exclude指定匹配模式,支持(匹配0+多個(gè)字符不包含目錄)? (匹配一個(gè)任意字符)*/ (遞歸匹配任意子目錄)
- 默認(rèn)所有可見的@types包都會(huì)在編譯時(shí)包含進(jìn)來(lái),node_modules/@types文件夾下以及子文件下所有包都是可見的,當(dāng)被置頂了typeRoots則只有被指定的包會(huì)被包含進(jìn)來(lái),指定了types則node_modules/@types下的這些包會(huì)被引入進(jìn)來(lái),可以通過(guò)指定types:[]來(lái)禁用自動(dòng)引入
基礎(chǔ)語(yǔ)法
1、number boolean string null undefined指定五種基本類型,void指定空值可以賦值為null undefined,反之void不可賦值給任何類型;any代表任意類型的值(類似不寫);類型推論,當(dāng)你定義變量的時(shí)候賦值,ts會(huì)根據(jù)你的賦值推出一個(gè)類型,不進(jìn)行賦值則會(huì)默認(rèn)為任意值;聯(lián)合類型:通過(guò)|分隔多個(gè)類型,訪問(wèn)屬性/方法時(shí)只能是共有的,當(dāng)賦值后則會(huì)類型推斷
2、接口:通過(guò)interface關(guān)鍵字進(jìn)行定義,?可選屬性、[propName: type] 自定義屬性(自定義屬性后,其他屬性必須為自定義屬性的子類)、readonly只讀屬性
- 接口描述了ts種復(fù)雜的類型結(jié)構(gòu),接口繼承自類的時(shí)候繼承了它的成員但是沒有繼承實(shí)現(xiàn),所以接口的功能只能由子類來(lái)實(shí)現(xiàn)。
3、數(shù)組類型number[]或者Array<number>;也可以通過(guò)接口定義(復(fù)雜),其他類數(shù)組類型有自己的類型定義如IArguments NodeList
4、函數(shù)有兩種定義方式,通過(guò)?進(jìn)行可選參數(shù)定義,只能寫在最后,如果是寫了默認(rèn)值的參數(shù),ts認(rèn)為是可選參數(shù),且無(wú)位置要求,通過(guò)解構(gòu)獲取剩余參數(shù),也可進(jìn)行定義
5、斷言 as語(yǔ)法:只要A兼容B或者B兼容A,就可以互相斷言,子類可以被斷言為一個(gè)父類,父類斷言可以為子類,是因?yàn)樽宇惏割惖乃袑傩裕梢栽L問(wèn)到父類的內(nèi)容
6、聲明文件一種是放在源碼里,通過(guò)types指定文件目錄;一種是補(bǔ)充到type庫(kù),最后是自己實(shí)現(xiàn).d.ts文件
7、type指定類型別名,類型約束
8、元組,賦值時(shí)需要匹配,可單獨(dú)賦值,可越界為聯(lián)合類型
9、enum 枚舉類型可以手動(dòng)覆蓋;可以包含計(jì)算值,下一個(gè)加一; 常數(shù)枚舉類型不可計(jì)算,外部枚舉類型 declare
10、類:public private protected abstract,抽象類必須被子類實(shí)現(xiàn)
11、接口繼承類:ts中的類在聲明時(shí)同時(shí)創(chuàng)建了一個(gè)同名的類型,它包含了屬性和方法,沒有constructor和static屬性,接口繼承時(shí)繼承了這部分類型,類似繼承了類生成的實(shí)例
類 接口 函數(shù)的用法
1、類 跟es6中的類差不多,添加了修飾符:public protected private,以及readonly;如果是抽象類abstract則不能直接實(shí)例化,抽象類中的抽象屬性和方法必須被子類實(shí)現(xiàn),類和接口很像,他們的區(qū)別在于:
- 類通過(guò)class實(shí)現(xiàn),通過(guò)extends繼承被子類繼承;接口是通過(guò)interface定義,被類所實(shí)現(xiàn)
- 類的方法可以自己實(shí)現(xiàn),抽象類子類必須實(shí)現(xiàn);接口則是一組規(guī)則的定義
- 類通常是對(duì)一個(gè)類別的公共部分做抽象,有規(guī)律;接口只是抽象,可能并無(wú)關(guān)聯(lián)
2、接口:接口中可以定義可選屬性,索引屬性,只讀屬性;也支持定義函數(shù)以及構(gòu)造函數(shù)的類型
- 函數(shù)重載 根據(jù)不同的參數(shù)個(gè)數(shù)指定不同的類型
- this指向 由于運(yùn)行時(shí)才能確定this指向,在ts中可以進(jìn)行手動(dòng)的this指向
3、泛型 通過(guò)T來(lái)代指當(dāng)運(yùn)行時(shí)才能確認(rèn)的類型,難點(diǎn)在于結(jié)合keyof和T<k>使用
4、兼容 如A=B,協(xié)變是B包含A,逆變是A包含B,雙向協(xié)變是沒有規(guī)則
對(duì)象、函數(shù)返回值、類中采用的是協(xié)變
函數(shù)參數(shù)個(gè)數(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) , 說(shuō)明返回值是協(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() {
// 必須要實(shí)現(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)