- npm i --save react react-dom @types/react @types/react-dom @types/前綴表示咱們額外要獲取react和react-dom的聲明文件。
- npm i --save-dev typescript awesome-typescript-loader source-map-loader ts-loader awesome-typescript-loader可讓Webpack使用TypeScript的標準配置文件tsconfig.json編譯TypeScript代碼。 source-map-loader使用TypeScript輸出的sourcemap文件來告訴webpack什麼時候生成本身的sourcemaps.這就容許你在調試最終生成的文件時候就好像在調試TypeScript源碼同樣 ts-loader 將typescript轉換成JavaScript;
- 根目錄下建立tsconfig.json文件
{
"compilerOptions": {
"outDir": "./dist/", //編譯js的輸出目錄
"sourceMap": true, // 編譯是否生成對應的source map文件
"noImplicitAny": true, //強類型檢查,沒法推斷類型時候,提示錯誤
"module": "commonjs", // 定義遵循的JavaScript模塊規範
"target": "es5", //遵循的標準
"jsx": "react",
"experimentalDecorators": true, // 啓用實驗性的裝飾器特性
},
"include": [
"./src/**/*" // 須要包含編譯的目錄
]
}
複製代碼
module.exports = {
entry: "./src/index.tsx",
output: {
filename: "bundle.js",
path: __dirname + "/dist"
},
devtool: "source-map",
resolve:{
extensions: [".ts", ".tsx", ".js", ".json"]
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: "awesome-typescript-loader"
},
{
enforce: "pre",
test: /\.js$/,
loader: "source-map-loader"
}
]
},
externals: {
"react": "React",
"react-dom": "ReactDOM"
}
}
複製代碼
ts中的數據類型有:Number數值類型,string字符串類型,Boolean布爾類型,enum枚舉類型, any任意類型,void空類型,Array數組類型,Tuple元祖類型,Null空類型。react
- 聲明數組 let arr:number = [];
- 給數組賦值
字面量賦值:let arr: number = [1,2,4]
構造函數賦值: let arr:Array<number> = new Array(1,2,3)
複製代碼
ts中,指定數據類型的數組只能存貯同一類型的數組元素webpack
- 元祖 元祖是特殊的數組,元祖類型容許表示一個已知元素數量和類型的數組,各元素的類型沒必要相同。
let arr:[string,number];
arr = ['12', 2];
arr = [2,'12'] // 報錯
複製代碼
基本類型字符串:用雙引號或者單引號括起來的一串字符串 引用類型字符串:用new實例化的String類型web
let jsan:string = '發就是電話';
let jsanpan:String = new String('1333吃')
console.log(jsan);
console.log(jsanpan); // 打印出的String {'1333吃'}
複製代碼
日期對象是Date實例,可用構造函數的方法進行建立,聲明這個日期變量時候,也要標明它的類型是Date,eg: let d:Date = new Date('2018/09/09 05:30:00')正則表達式
兩種方式:一種是字面量方式,一種是new關鍵字;經常使用test和exec測試字符串匹配typescript
let str:string = 'abcdefg';
let reg:RegExp = /ab/g;
let result:boolean = reg.test(str);
console.log(result); // true
let str2 = 'dapangzishuai'
let reg2:RegExp = new RegExp("dapang",'gi')
let reg3:RegExp = new RegExp("aaa",'gi')
let result:any = reg2.exec(str2);
let result2 = reg3.exec(str2);
console.log(result) //["dapang", index: 0, input: "dapangzishuai", groups: undefined]
console.log(result2) // null
複製代碼
爲了讓程序之間更有層次,變量之間互不干擾,利用命名空間來區分,成員須要用export導出npm
namespace a {
export class An {
name:string = '安安'
talk() {
console.log('女生安安')
}
}
}
namespace b {
export class An {
name:string='安安'
talk() {
console.log('男生安安')
}
}
}
let an1:a.An = new a.An();
let an2:a.An = new b.An();
console.log(an1.talk(),an2.talk(), '這是啥啊')
複製代碼
ts中的數據類型有:Number數值類型,string字符串類型,Boolean布爾類型,enum枚舉類型, any任意類型,void空類型,Array數組類型,Tuple元祖類型,Null空類型。json
默認值:默認值可讓你在屬性爲undefined的時候使用缺省值數組
function keepWholeObject(whoeObject: { a: string, b?: number }) {
let { a, b=101 } = whoeObject
console.log(a,b,'123是')
}
keepWholeObject({ a :'12', b : 10 });
複製代碼
函數聲明:bash
function f({ a, b } = { a: "", b: 0 }): void{
console.log(a, b, 'ab是');
}
f();
複製代碼
- 接口-interface eg: interface LabelledValue { label: string; }表明一個label屬性類型爲string的對象,若是不知足的話直接報錯
- 可選屬性 與普通的接口定義差很少,只是會在屬性名字後面加個?符號 eg:interface LabelledValue { label?: string; color?: string; } 優勢:能夠對可能存在的屬性進行預約義,若是有用到了不存在的屬性會報錯
- 只讀屬性-readonly 在屬性名前用readonly來指定只讀屬性
interface Point {
readonly x: number;
readonly y: number;
}
let point : Point = {
x: 10,
y: 10
}
// point.x = 5; 報錯,由於是隻讀屬性,不能夠進行修改
複製代碼
// ReadonlyArray<T>類型,把全部可變方法去掉了,確保數組建立後不再能被修改
let ro: ReadonlyArray<number> = [1,2,3,4];
ro[0] = 12; 報錯,屬性只讀不可修改
ro.push(4) 報錯,ReadonlyArray上沒有push這個方法
let a: number[] = [1,2,3,4];
let b: ReadonlyArray<number> = a;
a = b //報錯
a = b as number[]; //類型斷言從新寫,不報錯
複製代碼
判斷是用const仍是readonly,看他的用途,若是是變量使用的話用const,屬性使用則用readonlydom
- 額外的屬性檢查
1.避開它的檢查,用類型斷言的方式 eg: let mySquare = createSquare({colour: "red", width: 100} as SquareConfig) 即便SquareConfig中沒有colour這個屬性,也不會報錯
2.避開它的檢查,用索引簽名的方式 [propName: string]: any;
3.避開它的檢查,將這個對象賦值給另外一個變量,squareOptions不會通過額外屬性檢查 let squareOptions = { colour: 'red'}; let mysquare = createSquare(squareOptions);
- 函數類型 以下:函數類型時候,函數的參數名能夠不與接口裏定義的名字匹配,並且定義的屬性值也能夠不寫。
interface SearchFunc {
(source: string, subString: string) : boolean;
}
let mySearch: SearchFunc;
mySearch = function(source, subString) {
let result = source.search(subString);
return result > -1;
}
複製代碼
- 可索引的類型 可索引類型具備一個索引簽名,描述了對象索引的類型,還有相應的索引返回值類型; 以下,這個索引簽名表示當用number去索引StringArray時候會獲得string類型的返回值
interface StringArray {
[index: number]: string;
}
let myArray: StringArray;
myArray = ['Bob', 'Fred'];
let myStr: string = myArray[0];
複製代碼
- 類類型
靜態屬性:經過static關鍵字能夠聲明類型的靜態屬性。
- 接口的繼承 經過implements關鍵字繼承,接口的繼承能夠屢次繼承
interface Animal {
name: string;
eat(): void;
}
interface Person extends Animal {
use(): void;
}
class Dog implements Person {
name: string;
constructor(theName: string) {
this.name = theName;
}
eat() {
console.log(`${this.name}吃`)
}
use() {
console.log(`${this.name}胖`)
}
}
let dog: Person;
dog = new Dog('篩子');
dog.eat();
dog.use();
複製代碼
- 混合類型
- 接口繼承類
class Control {
private state: any;
}
interface SelectableControl extends Control {
select(): void;
}
class Button extends Control implements SelectableControl {
select() {
}
}
class TextBox extends Control {};
// SelectableControl包含了Control的全部成員,包括私有成員,因此Control的子類才能夠實現SelectableControl內的接口。Image不是SelectableControl的子類,因此以下寫法會報錯
// class Image implements SelectableControl {
// select(){}
// } //報錯
class Image extends Control implements SelectableControl {
select(){}
} //不報錯
複製代碼
- 以下:Animall是基類,Cat是派生類,Cat派生自基類Animall,經過extends關鍵字。派生類叫子類,基類一般叫超類。 類的繼承
class Animall {
name: string;
constructor(theName: string) {
this.name = theName;
}
eat() {
console.log(`動物叫${this.name}`)
}
}
let animall = new Animall('小狗');
animall.eat();
class Cat extends Animall{
constructor(theName: string) {
super(theName);
}
eat() {
super.eat();
console.log('吃狗糧')
}
}
let cat: Animall;
cat = new Cat('貓');
cat.eat();
class People extends Animall {
constructor(theName: string) {
super(theName);
}
eat() {
super.eat();
console.log(`${this.name}拒絕吃狗糧`);
}
}
let people: Animall;
people = new People('人');
people.eat();
複製代碼
子類經過關鍵字extends繼承,經過super方法調用基類的方法,也能夠重寫基類的方法。 public: 公有屬性,可賦值 protected: 受保護屬性,沒法賦值 private: 私有屬性,沒法賦值 protected成員在派生類中仍然能夠訪問,而private成員在派生類中也不能夠訪問。
eg:class Person {
protected name: string;
constructor (name: string) {
this.name = name;
}
}
class Employ extends Person {
private department: string;
constructor(name: string, department: string) {
super(name)
this.department = department;
}
public getMesage() {
return `hello, my name is ${this.name} 住在${this.department}`
}
}
let em = new Employ('an', 'beijing')
console.log(em.getMesage());
console.log(em.name); // 報錯,不能再person類之外使用name屬性,可是能夠在Employ中使用,由於Employ是Person派生
複製代碼
- 抽象類 抽象類做爲其餘派生類的基類,通常不會直接被實例化。abstract關鍵字用於定義抽象類和在抽象類內部定義抽象方法。
abstract class Department {
constructor(public name: string) { };
printName(): void {
console.log(`aaa${this.name}`)
};
abstract printMeeting(): void; // 必須在派生類中實現
}
class AccountDeparment extends Department {
printMeeting(): void {
console.log('111')
}
generator(): void {
console.log('222')
}
}
let department: Department; // 容許建立一個對抽象類型的引用
// department = new Department(); // 報錯,不能建立一個抽象類的實例
department = new AccountDeparment('an'); // 容許對一個抽象子類進行實例化和賦值
department.printName();
department.printMeeting();
// department.generator(); // 報錯,類型Department上不存在generator
複製代碼
- 高級技巧
class Greeter {
static standardGreeting = 'hello there';
greeting: string;
greet() {
if (this.greeting) {
return `hello ${this.greeting}`
} else {
return Greeter.standardGreeting
}
}
}
let greet1 : Greeter;
greet1 = new Greeter();
console.log(greet1.greet());
/**建立一個greeterMaker變量,保存了這個類或者說保存了類構造函數。使用typeof Greeter意思是取Greeter類的類型而不是實例的類型。
確切的說就是‘告訴Greeter標識符的類型,也就是構造函數的類型,這個類型包含了類的全部靜態成員和構造函數。’而後在greeterMaker上使用new,建立Greeter的實例
* */
let greeterMaker: typeof Greeter = Greeter;
greeterMaker.standardGreeting = 'hello';
let greet2: Greeter = new greeterMaker();
console.log(greet2.greet());
複製代碼
- 可選參數 ts中每一個參數都是必須的,多傳少傳都會報錯,當想實現可選參數的時候,在參數名旁邊使用?實現可選參數的功能。可是可選參數必須放在必須參數的後面
function add(par1: string, par2: string) {
return `${par1}額${par2}`
}
// let result1 = add('貓'); 報錯 少一個參數
// let result2 = add('貓', '狗', '魚'); 報錯,多一個參數
let result3 = add('貓', '狗');
function add2(par1: string, par2?: string) {
return `${par1}額${par2}`
}
// let result1 = add('貓'); 不報錯
// let result2 = add('貓', '狗', '魚'); 報錯,應該有1-2個參數,可是出現了3個
let result3 = add('貓', '狗');
複製代碼
- 默認參數 在全部必須參數後面的帶默認初始化的參數都是可選的,與可選參數同樣,在調用函數時候能夠省略 帶默認值的參數不用必須放在必須參數的後面,若是帶默認值的參數要出如今必須參數前面時候,必須明確的傳入undefined值。
function person(name: string, age = 18){
return `名字是${name},年齡是${age}歲`
}
let re = person('an');
let re2 = person('an', undefined); // age爲18
// let re3 = person('an', 20, 'anm'); //報錯
let re4 = person('am', 22);
console.log(re,re2, re4);
複製代碼
- 剩餘參數 定義:不知道有多少個參數將要傳進來,可能0個可能多個,把全部參數收集到一個變量裏 編輯器建立參數數組,名字是你在...後面定的名字,能夠在函數體內使用這個數組。
function person (name: string, ...params: string[]) {
return params;
}
let re = person('an', '18', 'amy');
console.log(re, 're是') // ['18','amy']
複製代碼
- this
- 重載
使用any類型能夠接收任何類型的arg參數,傳入的類型與返回的類型應該是相同的,可是用了any,咱們傳入一個數字,任何類型的值都有可能被返回
function identity(arg: any): any {
return arg;
}
複製代碼
類型變量T:一種特殊的變量,只用於表示類型而不是值,使得返回值的類型與傳入的參數的類型是相同的
- 泛型函數,適用於多個類型,不會丟失信息,傳入數值類型而且返回數值類型
function identity<T>(arg: T): T {
return arg;
}
// 第一種方法明確指定了T的類型,
let outPut = identity<string>('eww');
// 第二種方法,類型推論
let output2 = identity('90');
function a<T>(arg: T) : T {
console.log(arg.length); // 報錯,類型T上不存在屬性length,由於傳入的多是number
return arg;
}
// 泛型函數b,接收類型參數T和參數arg,它是個元素類型是T的數組,並返回元素相似是T的數組
function b<T>(arg: T[]) : T[] {
console.log(arg.length); // 不報錯
return arg;
}
複製代碼
- 泛型接口
interface Generic {
<T>(arg: T) : T;
}
function identity<U>(arg: U): U {
return arg;
}
let aa: Generic = identity;
複製代碼
- 泛型類,使用<>括起泛型類型,跟在類名後面。指的是實例部分的類型,因此類的靜態屬性不能使用這個泛型類型
class Person<T> {
zeroValue: T;
add: (x: T, y: T) => T
};
let person = new Person<number>();
person.zeroValue = 1;
let a = person.add = function(x,y) {
return x + y;
}
複製代碼
- 泛型約束 定義一個接口來描述約束條件,使用這個接口和extends關鍵字來實行約束
interface len {
length: number
}
function logging<T extends len>(arg: T) : T {
console.log(arg.length);
return arg;
}
// logging(333); //報錯,類型‘333’的參數不能賦給類型‘len’的參數;
logging('123');
複製代碼
- 枚舉經過關鍵字enum來定義,使用枚舉能夠定義一些有名字的數字常量,一個枚舉類型能夠包含零個或者多個枚舉成員. 沒有初始化函數而且以前的枚舉成員是常數,在這種狀況下,當前枚舉成員的值爲上一個成員的值加1,可是第一個若是沒有初始化方法那它的初始值爲0
enum Enum{
A
}
let a = Enum.A;
let b = Enum[a];
console.log(a,b) // a是0,b是‘A’
複製代碼
- 常數枚舉 :在enum關鍵字前使用const修飾符,只能使用常數枚舉表達式
const enum Par {
A = 1,
B = A*2
}
複製代碼
- 外部枚舉:描述已經存在的枚舉類型的形狀,避免重複的問題
declare enum Enum {
A = 1, // 標識符重複
B = A * 2,
}
複製代碼
- symbol類型的值是經過Symbol構造函數建立,並且是不可改變的唯一的,能夠被用做對象屬性的鍵
模塊是自聲明的,兩個模塊之間的關係是經過在文件級別上使用imports和exports創建的。
- 導出聲明 任何聲明,好比變量,函數,類,類型別名或接口都可以添加export關鍵字來導出。
- 導出語句 可能須要對導出的部分重命名 eg:export { ZipCode }; export { ZipCode as main };
- 從新導出 從新導出功能並不會在當前模塊導入那個模塊或者定義一個新的局部變量 或者一個模塊能夠包裹多個模塊,並把他們導出的內容聯合在一塊兒經過語法: export * from 'module'
- 導入 導入內容從新命名: import { a as b } from ''
- 將整個模塊導入到一個變量,經過它來訪問模塊的導出部分
import * as validator from "./ZipCodeValidator";
let myValidator = new validator.ZipCodeValidator();
複製代碼
- 默認導出
默認導出使用default關鍵字標記,一個模塊只能有一個default導出。