ts 是什么状知?
- Typescript 是JavaScript的超集,遵循ES5/ES6規(guī)范孽查,擴(kuò)展了Javascript語法饥悴;
- 越來越多的項目是基于TS,VSCode、Angular6西设、Vue3瓣铣、React16;
- TS提供的類型系統(tǒng)可以幫助我們在寫代碼的時候提供更豐富的語法提示贷揽;
- 在創(chuàng)建前的編譯階段經(jīng)過類型系統(tǒng)的檢查棠笑,就可以避免很多線上的錯誤
ts安裝和編譯
npm install typescript -g
tsc hello.ts
tsc hello.ts hello1.ts hello2.ts
在開發(fā)的過程中,不同文件中出現(xiàn)同變量名是會出現(xiàn)沖突擒滑「溃可以在文件中添加
export {}
tsc --init // 生成配置文件tsconfig.json
tsc // 全局編譯
tsc --watch // 文件改變自動編譯
tsconfig.json
{
"compilerOptions": {
/* Basic Options */
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. 指定ECMAScript的目標(biāo)版本*/
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. 指定模塊代碼的生成方式*/
// "lib": [], /* Specify library files to be included in the compilation. 指定編譯的時候用來包含的編譯文件*/
// "allowJs": true, /* Allow javascript files to be compiled. 允許編譯JS文件*/
// "checkJs": true, /* Report errors in .js files. 在JS中包括錯誤*/
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. 指定JSX代碼的生成方式 是保留還是react-native或者react*/
// "declaration": true, /* Generates corresponding '.d.ts' file.生成相應(yīng)的類型聲明文件 */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. 為每個類型聲明文件生成相應(yīng)的sourcemap*/
// "sourceMap": true, /* Generates corresponding '.map' file. 生成對應(yīng)的map文件 */
// "outFile": "./", /* Concatenate and emit output to single file. 合并并且把編譯后的內(nèi)容輸出 到一個文件里*/
// "outDir": "./", /* Redirect output structure to the directory.按原始結(jié)構(gòu)輸出到目標(biāo)目錄 */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. 指定輸入文件的根目錄,用--outDir來控制輸出的目錄結(jié)構(gòu)*/
// "composite": true, /* Enable project compilation 啟用項目編譯*/
// "removeComments": true, /* Do not emit comments to output. 移除注釋*/
// "noEmit": true, /* Do not emit outputs. 不要輸出*/
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. 當(dāng)目標(biāo)是ES5或ES3的時候提供對for-of丐一、擴(kuò)展運算符和解構(gòu)賦值中對于迭代器的完整支持*/
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule').r把每一個文件轉(zhuǎn)譯成一個單獨的模塊 */
/* Strict Type-Checking Options */
//"strict": true, /* Enable all strict type-checking options. 啟用完全的嚴(yán)格類型檢查 */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. 不能使用隱式的any類型*/
// "strictNullChecks": true, /* Enable strict null checks. 啟用嚴(yán)格的NULL檢查*/
// "strictFunctionTypes": true, /* Enable strict checking of function types. 啟用嚴(yán)格的函數(shù)類型檢查*/
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions.啟用函數(shù)上嚴(yán)格的bind call 和apply方法 */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. 啟用類上初始化屬性檢查*/
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type.在默認(rèn)的any中調(diào)用 this表達(dá)式報錯 */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. 在嚴(yán)格模式下解析并且向每個源文件中發(fā)射use strict*/
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. 有未使用到的本地變量時報錯 */
// "noUnusedParameters": true, /* Report errors on unused parameters. 有未使用到的參數(shù)時報錯*/
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. 當(dāng)不是所有的代碼路徑都有返回值的時候報錯*/
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. 在switch表達(dá)式中沒有替代的case會報錯 */
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). 指定模塊的解析策略 node classic*/
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. 在解析非絕對路徑模塊名的時候的基準(zhǔn)路徑*/
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. 一些路徑的集合*/
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. 根目錄的列表藻糖,在運行時用來合并內(nèi)容*/
// "typeRoots": [], /* List of folders to include type definitions from. 用來包含類型聲明的文件夾列表*/
// "types": [], /* Type declaration files to be included in compilation.在編譯的時候被包含的類型聲明 */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking.當(dāng)沒有默認(rèn)導(dǎo)出的時候允許默認(rèn)導(dǎo)入,這個在代碼執(zhí)行的時候沒有作用库车,只是在類型檢查的時候生效 */
//"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'.*/
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks.不要symlinks解析的真正路徑 */
/* Source Map Options */
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. 指定ts文件位置*/
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. 指定 map文件存放的位置 */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. 源文件和sourcemap 文件在同一文件中巨柒,而不是把map文件放在一個單獨的文件里*/
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. 源文件和sourcemap 文件在同一文件中*/
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. 啟動裝飾器*/
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
}
}
ts數(shù)據(jù)類型
- 任意類型(any): 聲明為 any 的變量可以賦予任意類型的值;
let b:any = 1;
- any就是可以賦值給任意類型
- 第三方庫沒有提供類型文件時可以使用any
- 類型轉(zhuǎn)換遇到困難時
- 數(shù)據(jù)結(jié)構(gòu)太復(fù)雜難以定義
- 數(shù)字類型(number)
let age:number = 18;
- 字符串類型(string)
let name: string = 'cc'
- 布爾類型(boolean)
let flag: boolean = true
- 數(shù)組類型(array)
// 在元素類型后面加上[]
let arr: number[] = [1, 2, 3]
// 使用數(shù)組泛型
let arr: Array<number> = [1, 2, 3]
- 元組類型(tuple): 元組類型用來表示已知元素數(shù)量和類型的數(shù)組,各元素的類型不必相同柠衍,對應(yīng)位置的類型需要相同洋满。
let p: [string, age] = ['cc', 18]
元組 vs 數(shù)組
元組 | 數(shù)組 |
---|---|
每一項可以是不同的類型 | 每一項都是同一種類型 |
有預(yù)定義的長度 | 沒有長度限制 |
用于表示一個固定的結(jié)構(gòu) | 用于表示一個列表 |
- 枚舉類型(enum):枚舉類型用于定義數(shù)值集合;默認(rèn)情況下珍坊,從0開始為元素編號牺勾。也可手動修改指定成員的數(shù)值。
enum Color { Red, Green, Blue };
let c: Color = Color.Blue;
console.log(c); // 輸出 2
- void:用于標(biāo)識方法返回值的類型,表示該方法沒有返回值
function hello(name: string):void {
console.log(`hello, ${name}`)
}
注:
- 當(dāng)我們聲明一個變量類型是 void 的時候,它的非嚴(yán)格模式(strictNullChecks:false)下僅可以被賦值為 null 和 undefined甲雅;
- 嚴(yán)格模式(strictNullChecks:true)下只能返回undefined
- null 和 undefined
- null 和 undefined 是其它類型的子類型,可以賦值給其它類型
- 嚴(yán)格模式(strictNullChecks:true)下不屬于任何一個類型回还,只能賦值給自己這種類型或者any
// 非嚴(yán)格
let a: number;
a = null
a = undefined
// 嚴(yán)格
let b: number | undefined | null;
b = 1;
b = null;
b = undefined;
- never:never 是其它類型(包括 null 和 undefined)的子類型,代表從不會出現(xiàn)的值叹洲。
- 拋出異常的情況
- 無限循環(huán)的情況
never 和 void 的區(qū)別柠硕?
- void 可以被賦值為 null 和 undefined的類型。 never 則是一個不包含值的類型
- 擁有 void 返回值類型的函數(shù)能正常運行运提。擁有 never 返回值類型的函數(shù)無法正常返回蝗柔,無法終止,或會拋出異常民泵。
ts變量聲明
- 聯(lián)合類型(Union Types): 表示取值可以為多種類型中的一種诫咱。
注:在未賦值時聯(lián)合類型上只能訪問兩個類型共有的屬性和方法。
let ss: string | number;
// 在這里只能獲取 string 和 number 類型的共有屬性和方法
if (typeof ss === 'string') {
// 可以獲取字符串的屬性和方法
} else {
// 可以獲取數(shù)值的屬性和方法
}
- 類型斷言(Type Assertion): 類型斷言可以用來手動指定一個值的類型洪灯,即允許變量從一種類型更改為另一種類型。
程序員 強(qiáng)行告訴ts是一個什么類型。
// <類型>值
let str:string = '1'
let str1:number = <number> <any> str
console.log(str1)
// 值 as 類型
let ss: string | number;
let s = (ss as string).length;
let n = (ss as number).toFixed(2);
- 當(dāng) S 類型是 T 類型的子集签钩,或者 T 類型是 S 類型的子集時掏呼,S 能被成功斷言成 S。
- 當(dāng)你在TypeScript里使用JSX時铅檩,只有 as 語法斷言是被允許的憎夷。
- 類型推斷:當(dāng)類型沒有給出時,ts 編譯器利用類型推斷來推斷類型昧旨。
- 定義時未賦值就會被推斷成any類型
- 定義時賦值就能利用類型推斷出類型
let s; // 定義時未賦值拾给,推斷成any
s = 1;
s = '1';
let num = 1 // 定義賦值,類型推斷為 number;
num = '1' // 再次賦值就會編譯錯誤
- 字面量類型: 可以把字符串兔沃、數(shù)字蒋得、布爾值字面量組成一個聯(lián)合類型
type cType = 1 | '1' | true
let c: cType = 1 // 變量c 為 1 '1' true 三者之一
- 交叉類型:將多個類型合并為一個類型。它包含了所有類型的特性乒疏。
interface Person {
id: string,
name: string
}
interface Master {
age: number
}
type Staff = Person & Master
const staff: Staff = {
id: '007',
name: 'cc',
age: 10
}
函數(shù)
- ts函數(shù) vs js函數(shù)
TypeScript | JavaScript |
---|---|
含有類型 | 無類型 |
箭頭函數(shù) | 箭頭函數(shù)(ES2015) |
函數(shù)類型 | 無函數(shù)類型 |
必填和可選參數(shù) | 所有參數(shù)都是可選的 |
默認(rèn)參數(shù) | 默認(rèn)參數(shù) |
剩余參數(shù) | 剩余參數(shù) |
函數(shù)重載 | 無函數(shù)重載 |
- 函數(shù)的定義: 可以指定參數(shù)的類型和返回值的類型
function sayName(name: string): string {
return `hello, ${name}`
}
- 函數(shù)表達(dá)式
// 定義一個類型额衙,用來約束函數(shù)表達(dá)式
type info = (name: string, age: number) => string;
let p: info = function(name: string, age: number): string {
return `hi, my name is ${name}, I'am ${age} years old`
}
p('cc', 19)
函數(shù)調(diào)用
實參的類型和個數(shù)必須和形參一一對應(yīng)可選參數(shù)
可選參數(shù)必須是最后一個參數(shù)。
function buildName(firstName: string, lastName?: string) {
if (lastName) {
return firstName + lastName
}
return firstName
}
buildName('c')
buildName('c', 'pc')
- 默認(rèn)參數(shù)
function person(name: string, age:number = 18): void {
console.log(age)
}
- 剩余參數(shù)
function sum(...numbers:number[]) {
return numbers.reduce((val,item)=>val+=item,0);
}
- 重載是方法名字相同怕吴,而參數(shù)數(shù)量或者類型不同窍侧,返回類型可以相同也可以不同。
// 為一個函數(shù)提供多個函數(shù)定義
function double(v: number): number; // 函數(shù)聲明
function double(v: string): string; // 函數(shù)聲明
function double(v: any): any { // 函數(shù)的實現(xiàn)转绷,必須緊跟在函數(shù)聲明后面
if (typeof v === 'number') return v * 2
if (typeof v === 'string') return v + v
}
類
- 定義類
- "strictPropertyInitialization": true // 啟用類屬性初始化的嚴(yán)格檢查
- 屬性初始化并賦值伟件;greeting: string = 'cc';
- 添加constructor(greeting: string) { this.greeting = greeting }
- greeting!: string;
class Greeter {
greeting: string;
constructor(greeting: string) {
this.greeting = greeting
}
greet(): string {
return 'Hello, ' + this.greeting; // this 表示的是類的成員
}
}
let greeter = new Greeter('cc')
public
可以省略
class Greeter {
constructor(public greeting: string) {}
}
- readonly
-
readonly
修飾的變量只能在構(gòu)造函數(shù)
中初始化 -
readonly
只是在編譯階段進(jìn)行代碼檢查。而const
在運行時檢查
class Person {
public readonly name: string;
constructor(name: string) {
this.name = name
}
}
let p = new Person('cc')
// p.name = 'yy'
- 修飾符
- puclic: 自己议经、子類斧账、其他都可以訪問
- protected: 自己和子類可以訪問,其他不能訪問
- private: 只能自己訪問爸业,子類和其他不能訪問
class Father {
public readonly name: string = 'dad';
protected age: number = 10;
private money: number = 10000;
}
class Son extends Father {
getName(): void {
console.log(this.name)
}
getAge(): void {
console.log(this.age)
}
// getMoney(): void {
// console.log(this.money) // money 為私有屬性
// }
}
- 類的繼承
extends
- 一次只能繼承一個類其骄,不支持繼承多個類,但 TypeScript 支持多重繼承(A 繼承 B扯旷,B 繼承 C)
- 繼承:子類繼承父類拯爽,子類除了擁有父類的所有特性外,還有一些更具體的特性
- 多態(tài):由繼承而產(chǎn)生了相關(guān)的不同的類钧忽,對同一個方法可以有不同的行為
類的靜態(tài)屬性和靜態(tài)方法
static
抽象類
abstract
- 抽象類是行為的抽象毯炮,一般來封裝一些公共屬性和方法
- 無法被實例化,只能被繼承
- 抽象方法不能在抽象類中實現(xiàn)耸黑,只能在抽象類的具體子類中實現(xiàn)桃煎,而且
必須
實現(xiàn)
abstract class Person {
name!:string;
abstract say():void;
}
class Man extends Person {
say():void {
console.log('Nice!')
}
}
- 接口里的方法都是抽象的
- 實現(xiàn)接口
implements
- 一個類只能繼承一個父類,但是可以實現(xiàn)多個接口
interface Runing {
run(): void;
}
interface Eating {
eat(): void;
}
class Man extends Person implements Runing, Eating {
say(): void {}
run(): void {}
eat(): void {}
}
- 重寫
- 重寫:子類重寫繼承自父類中的方法
- 重載:為同一個函數(shù)提供多個類型定義
接口
- 接口一方面可以在面向?qū)ο缶幊讨斜硎緸?code>行為的抽象大刊,另外可以用來描述
對象的形狀
- 接口就是把一些類中
共有的屬性和方法
抽象出來,可以用來約束
實現(xiàn)此接口的類
- 定義接口
//接口可以用來描述`對象的形狀`,少屬性或者多屬性都會報錯
interface Speakable{
speak(): void;
name?: string; // 为迈?表示可選屬性
}
let speakman:Speakable = {
speak() {},//少屬性會報錯
name: 'cc',
// age: 1//多屬性也會報錯
}
- 任意屬性
// 無法預(yù)先知道有哪些新的屬性的時候,可以使用 `[propName:string]: any`,propName名字是任意的
interface Person {
readonly id: number;
name: string;
[propName: string]: any;
}
- 接口的繼承
extends
- 函數(shù)類型接口:對方法傳入的參數(shù)和返回值進(jìn)行約束
interface computedAge {
(birth: number): number
}
let getAge: computedAge = function(birth: number): number {
return 2020 - birth
}
interface sumInterface {
(...args: number[]): number
}
let sum: sumInterface = (...args: number[]): number {
return args.reduce((a, b) => a + b, 0)
}
- 可索引接口:對數(shù)組或者對象進(jìn)行約束
interface Interface1 {
[index: number]: string
}
interface Interface2 {
[index: string]: string
}
泛型
- 軟件工程中,我們不僅要創(chuàng)建一致的定義良好的API,同時也要考慮
可重用性
葫辐。組件不僅能夠支持當(dāng)前
的數(shù)據(jù)類型搜锰,同時也能支持未來
的數(shù)據(jù)類型,這在創(chuàng)建大型系統(tǒng)時為你提供了十分靈活的功能耿战。 - 泛型(Generics)是指在定義函數(shù)蛋叼、接口或類的時候,不預(yù)先指定具體的類型剂陡,而在使用的時候再指定類型的一種特性
- 設(shè)計泛型的關(guān)鍵目的是在成員之間提供有意義的約束狈涮,這些成員可以是:類的實例成員、類的方法鸭栖、函數(shù)參數(shù)和函數(shù)返回值歌馍。
- 泛型類 用到了泛型的類
class CustomerGeneric<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
- 泛型接口
interface Point<A, B> {
a: A;
b: B;
}
function point<A, B> (a: A, b: B): Point<A, B> {
return { a, b }
}
point(1, 3)
- 泛型參數(shù)默認(rèn)類型
interface A<T=string> {
name: T;
}
let sa = { name: 'cc' }
let na = { name: 18 }
- 泛型的約束
interface LengthWise {
length: number
}
function logger<T extends LengthWise>(val: T) {
console.log(val.length) // 可以獲取length屬性
}
- 泛型工具類型
5.1 Partial:將某個類型里的屬性全部變?yōu)榭蛇x項 ?
type Partial<T> = {
[P in keyof T]?: T[P];
};
5.2 Required: 將傳入的屬性中的可選項變?yōu)楸剡x項
type Required<T> = { [P in keyof T]-?: T[P] };
5.3 Readonly:通過為傳入的屬性每一項都加上 readonly 修飾符來實現(xiàn)
type Readonly<T> = { readonly [P in keyof T]: T[P] }
5.4 Pick: 能夠幫助我們從傳入的屬性中摘取某一項返回
type Pick<T, K extends keyof T> = { [P in K]: T[P] };
5.5 Exclude: 將某個類型中屬于另一個的類型移除掉
type Exclude<T, U> = T extends U ? never : T;
5.6 Record: 將 K 中所有的屬性的值轉(zhuǎn)化為 T 類型
type Record<K extends keyof any, T> = {
[P in K]: T;
};
- 一些常見泛型變量代表的意思:
- T(Type):表示一個 TypeScript 類型
- K(Key):表示對象中的鍵類型
- V(Value):表示對象中的值類型
- E(Element):表示元素類型
類型變換
- 交叉類型: 把多個類型合并成一個大的總類型
interface Bird {
name: string
fly(): void
}
interface Person {
age: number;
talk(): void;
}
type BirdMan = Bird & Person
- typeof:獲取一個變量的類型;
先拿到一個對象,然后通過對象獲取纤泵,反推這個對象的類型
let p = { name: 'cc', age: 18 }
type Person = typeof p
let p1: Person = { name: 'yy', age: 17 }
- 索引訪問操作符
interface Person {
location: {
city: string
}
}
let p: Person['location'] = { city: 'beijing' }
- keyof 操作符可以用來一個對象中的所有 key 值
interface Person {
name: string;
age: number;
}
type K1 = keyof Person; // "name" | "age"
type K2 = keyof Person[]; // "length" | "toString" | "pop" | "push" | "concat" | "join"
type K3 = keyof { [x: string]: Person }; // string | number
- 批量操作
interface Person {
name: string;
age: number
}
type PersonType = {
[key in keyof Person]?: Person[key] // 批量將參數(shù)變成可選參數(shù)
}