一篇文章,讓你讀懂TypeScript


一篇文章,讓你讀懂TypeScript


TypeScript

TypeScript是一種由微軟開發的自由和開源的編程語言。它是JavaScript的一個超集,而且本質上向這個語言添加了可選的靜態類型和基於類的面向對象編程。今天本文就從安裝TypeScript環境出發,結合具體的實例來深入探索TypeScript。

1. 安裝

npm install -g typescript

2. vscode自動編譯

  • 項目目錄終端執行 tsc --init
  • 更改tsconfig.json “outDir”: “./js”

基礎語法


1. 數據類型

  • 布爾值
  • 數字
  • 字符串
  • 數組
  • 元組 Tuple
  • 枚舉
  • Any
  • Void (函數沒有返回值使用。)
  • Null 和 Undefined (默認情況下null和undefined是所有類型的子類型。)
  • Never (never類型是任何類型的子類型)
  • Object

2. 函數

聲明函數
function run():string {
return 'typescript';
}
匿名函數
var fun = function():string {
return 'typescript';
}
定義方法傳參
function user(name:string,age:number):string {
return `${name}----${age}`;
}
var user = function(name:string,age:number):string {
return `${name}----${age}`;
}
沒有返回值
function run():void {
console.log('typescript' );
}
方法可選參數
function user(name: string,age?:number):string {
return `${name}----${age}`;
}
方法參數默認值

function user(name: string,age:number=20):string {
return `${name}----${age}`;
}
方法剩餘參數
function user(...result:number[]):string {

}
function user(name: string,...result:number[]):string {

}
重載
function user(name: string):string;
function user(age: number):number;
function user(str:any):any {
if(typeof str==='string) {
return str
} else {
return str
}
}

3. 類

基本模型
class Person {
name: string; //屬性 省略publick 關鍵詞
constructor(name:string) { //構造函數 實例化的時候調用的方法(初始化對象)
this.name = name;
}
run():void {
alert(this.name);
}
}
class Person {
name: string; //屬性 省略publick 關鍵詞
constructor(name:string) { //構造函數 實例化的時候調用的方法(初始化對象)
this.name = name;
}
setName():void {
this.name = name;
}

getName():string {
alert(this.name);
}
}
var person1 = new Person('張三');
alert(person1.getName());
person1.setName('李四');
alert(person1.getName());

4. 繼承

class Person {
name: string; //屬性 省略publick 關鍵詞
constructor(name:string) { //構造函數 實例化的時候調用的方法(初始化對象)
this.name = name;
}
run():string {
return `${this.name}`
}
}
子類可以使用父類的屬性和方法 如果子類的方法或者屬性和父類相同 則以子類為主
class Web extends Person {
constructor(name:string) {
super(name); //初始化父類的構造函數
}
work():string {
return `${this.name}在運動`
}
run():string {
return `${this.name}`
}
}
var w = new Web('李四');
alert(w.run());

5. 類裡面的修飾符

  • public

共有類型 在類裡面、子類、類外面都可以訪問(默認,不寫默認就是)。

  • protected

保護類型 在類裡面、子類可以訪問,類外面都不可以訪問。

  • private

私有類型 在類裡面可以訪問,子類和類外面都不可以訪問。

6. 類的靜態屬性和靜態方法

  • static (靜態方法裡面不能直接調用類裡面的屬性,能調用靜態屬性)
class Person {
public name:string;
static age:number=20;
constructor(name) {
this.name = name;
}
run() {
alert(`${this.name}在運動`);
}
static print() {

alert(`print`+Person.age);
}
}

7. 多態

  • 父類定義一個方法不去實現,讓繼承它的子類去實現,讓每一個子類有不同的表現
class Animal {
name:string;
constructor(name:string){
this.name = name;
}
eat() {
console.log('吃的方法');
}
}
class Dog extends Animal {
constructor(name:string) {
super(name)
}
eat() {
return this.name + '骨頭'
}
}
class Cat extends Animal {
constructor(name:string) {
super(name)
}
eat() {
return this.name + '魚'
}
}

8. 抽象類

  • 提供標準
  • abstract 抽象類不能實例化 為子類提供基類
  • 子類必須實現父類的抽象方法
  • abstract必須放在抽象類裡面
abstract class Animal {
name:string;
constructor(name:string){
this.name = name;
}
abstract eat():any;
}
class Dog extends Animal {
constructor(name:any) {
super(name);
}
eat() {
console.log(this.name);
}
}

9. 接口

  • 定義規範 定義行為和動作的規範 (接口不關心類內部的數據狀態和方法實現的細節)
interface FullName {
firstName: string;
secondName: string;
}
function printName(name: FullName) {
console.log(name.firstName+ '--' +name.secondName)
}
var obj = {
firstName: 'sun',
secondName: 'yu'

}
printName(obj) // ok
接口的可選屬性
interface FullName {
firstName: string;
secondName?: string;
}
function printName(name: FullName) {
console.log(name.firstName+ '--' +name.secondName)
}
var obj = {
firstName: 'sun',
secondName: 'yu'
}
printName(obj) // ok
var obj = {
firstName: 'sun'
}
printName(obj) // ok
函數類型的接口
interface encrypt {
(key:string,value:string):string;
}
var md5:encrypt = function(key:string,value:string):string {
return key+value;
}
md5('key','value');
可索引接口 數組和對象的約束(不常用)
interface userArr {
[index:number]:string
}
var arr:userArr = ['string','string']; //ok
interface userObj {
[index:string]:string
}
var arr:userObj = ['string','string']; //ok
類類型接口 對類的約束
interface Animal {
name:string;
eat(str:string):void;
}
class Dog implements Animal {
name: string;
constructor(name:string) {
this.name = name;
}

eat() {
return `吃骨頭`;
}
}
var dog = new Dog('小黑');
dog.eat();
接口擴展 接口擴展接口
interface Animal {
eat():void;
}
interface Person extends Animal {
work():void;
}
class Web implements Person {
public name:string;
constructor(name:string){
this.name= name;
}
eat() {
console.log(this.name+'喜歡吃饅頭');
}
work() {
console.log(this.name+'愛工作');
}
}
---------------------------
interface Animal {
eat():void;
}
interface Person extends Animal {
work():void;
}
class programmer {
public: name:string;
constructor(name:string) {
this.name = name;
}
coding(code:string){
console.log(this.name+code);
}
}
class Web extends programmer implements Person {
constructor(name:string){
super(name)
}
eat() {
console.log(this.name+'喜歡吃饅頭');
}

work() {
console.log(this.name+'愛工作');
}
}

10. 泛型

interface FullName {
firstName: string;
secondName: string;
}
function printName(name: FullName) {
console.log(name.firstName+ '--' +name.secondName)
}
var obj = {
firstName: 'sun',
secondName: 'yu'
}
printName(obj) // ok
接口的可選屬性
interface FullName {
firstName: string;
secondName?: string;
}
function printName(name: FullName) {
console.log(name.firstName+ '--' +name.secondName)
}
var obj = {
firstName: 'sun',
secondName: 'yu'
}
printName(obj) // ok
var obj = {
firstName: 'sun'
}
printName(obj) // ok
函數類型的接口
interface encrypt {
(key:string,value:string):string;
}
var md5:encrypt = function(key:string,value:string):string {
return key+value;
}
md5('key','value');
可索引接口 數組和對象的約束(不常用)

interface userArr {
[index:number]:string
}
var arr:userArr = ['string','string']; //ok
interface userObj {
[index:string]:string
}
var arr:userObj = ['string','string']; //ok
類類型接口 對類的約束
interface Animal {
name:string;
eat(str:string):void;
}
class Dog implements Animal {
name: string;
constructor(name:string) {
this.name = name;
}
eat() {
return `吃骨頭`;
}
}
var dog = new Dog('小黑');
dog.eat();
接口擴展 接口擴展接口
interface Animal {
eat():void;
}
interface Person extends Animal {
work():void;
}
class Web implements Person {
public name:string;
constructor(name:string){
this.name= name;
}
eat() {
console.log(this.name+'喜歡吃饅頭');
}
work() {
console.log(this.name+'愛工作');
}
}
---------------------------
interface Animal {
eat():void;
}

interface Person extends Animal {
work():void;
}
class programmer {
public: name:string;
constructor(name:string) {
this.name = name;
}
coding(code:string){
console.log(this.name+code);
}
}
class Web extends programmer implements Person {
constructor(name:string){
super(name)
}
eat() {
console.log(this.name+'喜歡吃饅頭');
}
work() {
console.log(this.name+'愛工作');
}
}

11. 模塊

  • 模塊的概念(官方): ”內部模塊“=》”命名空間“,”外部模塊“=》”模塊“ 模塊在其自身的作用域裡面執行,而不是在全局作用域執行。這就意味著定義一個模塊裡的變量,函數,類等等在模塊外部是不可見的,除非你明確的使用export形式之一導出他們。相反,如果想使用其他模塊導出的變量,函數,類,接口等的時候,你必須要導入它們,可以使用import形式之一。
  • 模塊的概念(自己理解): 我們可以把一些公共的功能單獨抽離成一個文件作為一個模塊。模塊裡面的變量,函數,類等都是私有的,如果我們要在外部訪問模塊裡面的數據(變量,函數,類),我們需要通過export暴露模塊裡面的數據(變量、函數、類)暴露後我們通過import引用模塊裡面的數據(變量,函數,類)。
定義 db.ts
var a:string = "string";
function getData(value:string):string {
return value
}
export {
a,
getData
}
使用
import { a,getDate } form './db'
getData();
import { a,getData as get} form './db'
get();
定義 db.ts
exprot default function getData(value:string):string {
return value
}
使用
import getData form './db'
getData();

12. 命名空間

  • 命名空間和模塊的區別:命名空間,內部模塊,主要用於組織代碼,避免命名衝突。模塊,ts的外部模塊的簡稱,側重代碼的複用,一個模塊裡可能會有多個命名空間。
namespace A {
interface Animal {
name:string;
eat(str:string):void;
}
export class Dog implements Animal {
name: string;
constructor(name:string) {
this.name = name;

}
eat() {
return `吃骨頭`;
}
}
}
var dog = A.Dog("小黑");
dog.eat();
命名空間封裝成模塊
a.ts文件名
定義
export namespace A {
interface Animal {
name:string;
eat(str:string):void;
}
export class Dog implements Animal {
name: string;
constructor(name:string) {
this.name = name;
}
eat() {
return `吃骨頭`;
}
}
}
使用
import { a } from './a'
var dog = new a.Dog();
dog.eat();

13. 裝飾器

  • 裝飾器:裝飾器是一種特殊類型的聲明,它能夠被附加到類聲明,方法,屬性或參數上,可以修改類的行為。
  • 通俗的講裝飾器就是一個方法,可以注入到類、方法、屬性參數上來擴展類、屬性、方法、參數的功能。
  • 常見的裝飾器有:類裝飾器、屬性裝飾器、方法裝飾器、參數裝飾器。
  • 裝飾器寫法:普通裝飾器(無法傳參)、裝飾器工廠(可傳參)。
  • 裝飾器是過去幾年中js最大的成就之一,已經是Es7的標準特性之一。
1.類裝飾器(普通裝飾器,無法傳參)
function logClass(params:any){
console.log(params);
params.prototype.apiUrl="動態擴展的屬性";
params.prototype.run = function() {
console.log("我是run方法");
}
}
@logClass
httpClient {
constructor() {
}
getData() {
}
}
var H = new httpClient();
console.log(H.apiUrl);
H.run();
2.類裝飾器(裝飾器工廠,可傳參)
function logClass(params:string){
return function(target:any) {
target.prototype.apiUrl="動態擴展的屬性";
target.prototype.run = function() {
console.log("我是run方法");
}
}
}
@logClass('hello')
httpClient {

constructor() {
}
getData() {
}
}
把類賦值給target
把參數賦值給params
var H:any = new httpClient();
console.log(H.apiUrl);
H.run();
類裝飾器重載以前類的構造函數
function logClass(target: any) {
console.log(target);
return class extends target{
apiUrl:any = "我是修改後的url";
getData() {
console.log(this.apiUrl);
}
}
}
@logClass
httpClient {
public apiUrl: string | undefined;
constructor() {
this.apiUrl = 'url';
}
getData() {
console.log(this.apiUrl);
}
}
var http = new httpClient();
------------------------------
3.屬性裝飾器(屬性裝飾器表達式會在運行時當作函數調用,傳入下列兩個參數,對於靜態成員來說是類的構造函數,對於實例成員是類的原型對象)
function logClass(params:any){
console.log(params);
params.prototype.apiUrl="動態擴展的屬性";
params.prototype.run = function() {
console.log("我是run方法");
}
}

function logProperty(params:string){
return function(target: any,attr:any) {
console.log(target);
console.log(target[attr]);
target[attr] = params;
}
}
@logClass('xxx')
httpClient {
@logProperty("http://baidu.com");
public url: string | undefined;
constructor() {

}
getData() {
console.log(this.url);
}
}
var http = new httpClient();
http.getData();
4.方法裝飾器
它會被應用到的方法的屬性描述符上,可以用來監視,修改或者替換方法定義
方法裝飾器會在運行是傳入下列3個參數
(1)對於靜態成員來說類的構造函數,對於實例成員來說是類的原型對象。
(2)成員的名字。
(3)成員的屬性描述符。
function logMethod(params: any) {
return function(target:any,methodName:any,desc:any) {
console.log(target);
console.log(methodName);
console.log(desc);
target.apiUrl="動態擴展的屬性";
target.run = function() {
console.log("我是run方法");
}
}
}
httpClient {
constructor() {


}
@logMethod("http://baidu.com")
getData() {
console.log(this.url);
}
}
var http:any = new httpClient();
http.run();
------------------------------------------
function logMethod(params: any) {
return function(target:any,methodName:any,desc:any) {
console.log(target);
console.log(methodName);
console.log(desc);
//修改裝飾器的方法 把裝飾器方法傳入所以參數改為string類型
//保存當前的方法
var oMethod = desc.value;
desc.value = function(...args:any[]) {
args = args.map((value)=>{
return String(value)
});
console.log(args);
}
}
}
httpClient {
public url:any | undefined;
constructor() {

}
@logMethod("http://baidu.com")
getData() {
console.log(this.url);
}
}
var http:any = new httpClient();
http.getData(123,'xxx');

今天的內容就到這裡,喜歡的話給個轉發關注吧!


分享到:


相關文章: