1.ts介紹
微軟開(kāi)發(fā)的開(kāi)源編程語(yǔ)言物延,是js的超集谜疤。
2.安裝
yarn global add typescript
3.運(yùn)行
編譯ts文件
tsc index.ts
初始化配置文件
tsc --init
會(huì)生成tsconfig.json文件
4.ts中的數(shù)據(jù)類型
布爾類型(boolean)
數(shù)字類型 (number)
字符串類型 (string)
數(shù)組類型 (array)
元組類型 (tuple)
枚舉類型(enum)
任意類型(any)
unknown
null和undefined
void類型
never類型
- 布爾類型选脊,數(shù)字類型澎怒,字符串類型
let bol:boolean=true; //只能是true或者false
let bol1:boolean=undefined; // error
let str:string=""; // 只能是字符串
let str1:string="aa"; // 只能是字符串
let num: number=1;//整數(shù)可以
let num1:number=1.12; //浮點(diǎn)數(shù)可以
let num2:number=NaN;//NaN可以
- 數(shù)組類型
let arr:number[]=[1,2,3,4]// 純數(shù)字?jǐn)?shù)組
let arr2:string[]=['1','2']// 純字符串?dāng)?shù)組
let arr3:string[]=[]// 允許是空數(shù)組
arr3.push("123")// ok
arr3.push(123)// error 數(shù)組只能包含字符串
let arr4:any[]=[1,false,'haha'];//任意類型填充的數(shù)組用any
數(shù)組的另一種表示方法
let arr5:Array<string>=['hahah'];
let arr6:Array<number>=[1,2,3];
褒搔。。丹拯。
- 元組類型tuple(數(shù)組的一種)
個(gè)數(shù)站超、類型必須嚴(yán)格遵守
let arr:[string,number]=['haha',12];
let arr1:[string,number]=['haha'];//error
let arr2:[string,number]=['haha',12,1];//error
- 枚舉類型(enum)
提升代碼的可讀性,可用于將狀態(tài)碼映射成數(shù)字
enum Flag {
success=1,
error=-1
}
let f:Flag=Flag.success; //1
Flag.success //1
Flag.error // -1
沒(méi)有賦值的情況
enum Color {
red,
blue,
orange=10,
black,
}
//如果沒(méi)有賦值就取自己的索引乖酬,如果有值就取值死相,后邊的是前邊的值+1
Color.red // 0
Color.blue // 1
Color.orange // 10
Color.black // 11
- 任意類型 any
let n:any=123;//可以賦任何值
n='haha';
n=false;
n.foo.bar; // OK 不進(jìn)行驗(yàn)證
n.trim(); // OK 不進(jìn)行驗(yàn)證
let arr:any[]=[1,false,'haha']//可以是任何類型
- unknown類型
// unkonwn 類型只能被賦值給any和unknown本身 只有能保存任意類型值的容器才能保存unknown本身
let u: unknown = 123;
u='aaa';
let a: string = u; // not ok;
- null和undefined
let un:undefined;
console.log(un)//輸出undefined
//“或者”用“ | ”表示
let un2:number | undefined | string | null;
un2=11;
console.log(un2);//11
let un3:null;
console.log(un3)//error 因?yàn)槭莡ndefined
let un4:null;
un4=null
console.log(un4)//null
let un5:null=null;
console.log(un5)//null
- void類型:ts中的void表示沒(méi)有任何類型,一般用于定義的方法沒(méi)有返回值
function fn():void{
console.log(1)
}
fn()//1
function fn2():void{
console.log(1)
return 1
}
//error
- never類型
var a:never;
a=(()=>{
throw new Error('錯(cuò)誤');
})()
5.函數(shù)的寫法
//設(shè)置返回值必須是字符串
function run():string{
return 'haha';
}
let run2=function():string{
return 'haha';
}
//設(shè)置函數(shù)參數(shù)的類型
let run3=function(name:string,age:number):string{
return `${name}---${age}`;
}
run3('ts',20)// 'ts---20'
//沒(méi)有返回值的函數(shù)
let run4=function(name:string,age:number):void{
console.log( `${name}---${age}`)
}
run4('ts',20)// 'ts---20'
//可選參數(shù) " ? " 表示咬像,可選參數(shù)必須配置到參數(shù)的最后面
let run5=function(name:string,age?:number):string{
if(age){
return `${name}---${age}`
}else{
return `${name}---空`
}
run5('ts',20)// 'ts---20'
run5('ts')// 'ts---空'
//默認(rèn)參數(shù)
let run6=function(name:string,age:number=10):void{
console.log( `${name}---${age}`)
}
run6('ts',20)// 'ts---20'
run6('ts')// 'ts---10'
//剩余參數(shù)
function sum(a:number,b:number,c:number):number{
return a+b+c
}
sum(1,2,3)//6
function sum2(...res:number[]):number{
return res.reduce((prev,next)=>{
return prev+next
},0)
}
sum2(1,2,3)//6
function sum4(a:number,...res:number[]):number{
return res.reduce((prev,next)=>{
return prev+next
},a)
}
sum4(1,2,3)//6
//ts函數(shù)的重載(重載指的是兩個(gè)或者以上的同名函數(shù)算撮,但他們參數(shù)不一樣生宛,這是會(huì)出現(xiàn)重載的情況)
function getInfo(name:string):string
function getInfo(age:number):string
function getInfo(str:any):any{
if(typeof str==='string'){
return `name-${str}`
}else{
return `age-${str}`
}
}
getInfo('zhang')// name-zhang
getInfo(12)// age-12
//箭頭函數(shù) 和以上規(guī)則一致
var fun3 = (a:number, b:number):number=>{
return a+b;
}
- ts中的類class
class Person{
name:string;
constructor(n:string){
this.name=n;
}
run():void{
alert(this.name);
}
work():string{
return this.name;
}
}
var p=new Person('張三');
p.run();//張三
//類的繼承
class Workers extends Person{
constructor(name:string){
super(name);
}
}
let work = new Workers('里斯');//里斯
work.run()
//類里邊的修飾符 ts里邊定義屬性的時(shí)候提供了三個(gè)修飾符
//public公有的 :< 在類里邊、子類肮柜、類外邊都可以訪問(wèn) >
//protected受保護(hù)的 : < 在類里邊陷舅、子類里邊可以訪問(wèn)、在類外部沒(méi)法訪問(wèn) >
//private私有的 : < 在類里可以訪問(wèn)审洞,子類莱睁、類外部都沒(méi)法訪問(wèn) >
//屬性如果不加修飾符默認(rèn)是 public 公有的
class Person{
public name:string;//------可不寫public-------
constructor(n:string){
this.name=n;
}
run():string{
return this.name//類里邊訪問(wèn)
}
}
var p=new Person('張三');
p.name;//類外邊訪問(wèn)
class Workers extends Person{
constructor(name:string){
super(name);
}
work():void{
alert(this.name)//子類里邊訪問(wèn)
}
}
//-----------protected受保護(hù)的-------------
class Person{
protected name:string;
constructor(n:string){
this.name=n;
}
run():string{
return this.name//類里邊訪問(wèn)
}
}
var p=new Person('張三');
p.name;//-----------類外邊訪問(wèn) error---------
class Workers extends Person{
constructor(name:string){
super(name);
}
work():void{
alert(this.name)//子類里邊訪問(wèn)
}
}
//---------------private--------------------
class Person{
private name:string;
constructor(n:string){
this.name=n;
}
run():string{
return this.name//類里邊訪問(wèn)
}
}
var p=new Person('張三');
p.name;//-----------類外邊訪問(wèn) error-----------
class Workers extends Person{
constructor(name:string){
super(name);
}
work():void{
alert(this.name)//------子類里邊訪問(wèn) error-----------
}
}
//ts中的抽象類,他是提供繼承的基類芒澜,不能被直接實(shí)例化
//用abstract關(guān)鍵字定義抽象類和抽象方法仰剿,抽象類中的抽象方法不包含具體實(shí)現(xiàn)并且必須在派生類中實(shí)現(xiàn)
//abstract的抽象方法只能放到抽象類中
abstract class Animal{
public name:string;
constructor(name:string){
this.name=name;
}
abstract eat():any;
run(){
console.log('其他方法可以不實(shí)現(xiàn)')
}
}
let a=new Animal()//錯(cuò)誤的寫法
class Dog extends Animal{
constructor(name:string){
super(name);
}
//**抽象類的子類必須實(shí)現(xiàn)抽象類里邊的抽象方法**
eat(){
console.log(this.name)
}
}
let d=new Dog('狗');
d.eat();
6.接口 interface
接口的作用:在面向?qū)ο蟮木幊讨校涌谑且环N規(guī)范的定義痴晦,它定義了行為和動(dòng)作的規(guī)范南吮,在程序設(shè)計(jì)里面,接口起到一種限制和規(guī)范的作用誊酌。接口定義了某一批所需要遵守的規(guī)范部凑,接口不關(guān)心這些類內(nèi)部狀態(tài)數(shù)據(jù),也不關(guān)心類方法里的實(shí)現(xiàn)細(xì)節(jié)碧浊,他只規(guī)定這批類必須提供的某些方法涂邀,提供這些方法的類就可以滿足實(shí)際需要。
-
接口類型:
屬性類接口辉词、函數(shù)類型接口必孤、可索引接口猾骡、類類型接口瑞躺、接口拓展1.屬性類接口 對(duì)json的約束
function fn1(obj:{name:string}):void{ console.log(obj.name) } fn1({name:'hello'})// hello fn1({name:123})// error fn1({name:'hello',age:2})// error //interface寫法 對(duì)批量方法傳入?yún)?shù)都進(jìn)行約束 interface FullName{ firstName:string; //注意‘ ; ’結(jié)束 lastName:string; }; function fn2(obj:FullName):string{ return obj.firstName+obj.lastName; } fn2({firstName:'hello',lastName:'ts'});//必須只包括著兩個(gè)屬性 fn2({firstName:'hello',lastName:'ts',age:12});// error let obj={ firstName:'hello', lastName:'ts', age:12 } fn2(obj);//這樣傳入的obj只要包含兩個(gè)屬性即可,但是函數(shù)內(nèi)不允許使用age屬性 //可選屬性接口 interface FullName{ firstName:string; //注意‘ ; ’結(jié)束 lastName?:string; }; //可以這么用 fn2({firstName:'aaa'}); fn2({firstName:'aaa',lastName:'bbb'});
2.函數(shù)類型接口:對(duì)方法傳入的參數(shù) 以及返回值進(jìn)行約束
interface encrypt{ (key:string,value:string):string } let md5:encrypt=function(key:string,value:string):string{ return key+value; } // 或這樣寫 let md6:encrypt=function(key,value){ return key+value; }
- 可索引接口: 對(duì)數(shù)組兴想、對(duì)象的約束(不常用)
// let arr:number[]=[1,2,3];//數(shù)組類型 // 對(duì)數(shù)組的約束 interface UserArr{ [index:number]:string// index屬性是number類型幢哨,值是string類型 } let arr:UserArr=['1','2'] // 對(duì)對(duì)象的約束 interface UserArr{ [index:string]:string// index屬性是string類型,值是string類型 } let obj:UserArr={name:'aaa'}
- 類類型接口(implements) 和抽象類相似
interface Animal{ name:string; eat(str:string):void; } // Dog必須包含name和eat class Dog implements Animal{ name:string; constructor(name:string){ this.name=name; } eat(str:string):void{ console.log(this.name+str) }; run(str:string):void{ console.log('run'); } } let d=new Dog('小黑'); d.eat('古嫂便,頭')
- 接口擴(kuò)展捞镰,接口可以繼承接口
interface Animal1{ eat():void; } interface Person1 extends Animal1{ work():void; } class Web1 implements Person1{ constructor(){/**do some**/} eat(){/**do some**/}; work(){/**do some**/} } let w=new Web1(); class Pro{ public name:string; constructor(name:string){ this.name=name; } coding(code:string):void{ console.log(this.name+code) } //add eat ,Web2就可以不用再定義eat eat(){}; } class Web2 extends Pro implements Person1{ constructor(name:string){ super(name) } // eat(){}; work(){} } let w2=new Web2('123');
type類型別名
- 類型別名會(huì)給一個(gè)類型起個(gè)新名字。 類型別名有時(shí)和接口interface很像毙替,但是可以作用于原始值岸售,聯(lián)合類型,元組以及其它任何你需要手寫的類型厂画。
- 可以使用 &交叉類型 和 |聯(lián)合類型凸丸。
- 不能使用extends和implements
interface定義一個(gè)實(shí)實(shí)在在的接口,是一個(gè)真正的類型 / type一般指一個(gè)別名袱院,不會(huì)產(chǎn)生真實(shí)的類型屎慢。
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
type Container<T> = { value: T };
7.泛型<T>
為了組件的靈活性瞭稼,組件不僅能夠支持當(dāng)前的數(shù)據(jù)類型,同時(shí)也應(yīng)該能支持未來(lái)的數(shù)據(jù)類型腻惠,环肘,一個(gè)組件可以支持多種數(shù)據(jù)類型。這樣用戶就可以以自己的數(shù)據(jù)類型來(lái)使用組件集灌。
泛型就是解決 類悔雹、接口、方法的復(fù)用性欣喧、以及對(duì)不特定的數(shù)據(jù)類型的支持(類型校驗(yàn))
- 泛型函數(shù)
// any可以解決問(wèn)題荠商,它放棄了類型檢查
// 泛型:可以支持不特定的數(shù)據(jù)類型,要求傳入的參數(shù)和返回的參數(shù)一致
function getData<T>(value:T):T{// T表示泛型续誉,具體什么類型是調(diào)用這個(gè)方法的時(shí)候決定的
return value
}
getData<number>(123);//參數(shù)必須是number
getData<string>('123');//參數(shù)必須是string
getData<number>('aaa'); // error
- 泛型類
class MinClass<T>{
public list:T[]=[];
add(value:T):void{
this.list.push(value);
}
min():T{
let min=this.list[0];
for(let i=0;i<this.list.length;i++){
if(min>this.list[i]){min=this.list[i]}
}
return min;
}
}
let m1=new MinClass<number>()//傳入的參數(shù)只能是number
//實(shí)例化類莱没,并且制定了類的T代表的類型是number
m1.add(2);
m1.add(1);
m1.add(3);
m1.min();
react中使用泛型
type Props = {
className?: string
...
};
type State = {
submitted?: bool
...
};
class MyComponent extends React.Component<Props, State> {
...
}
- 泛型接口
interface ConfigFn{
<T>(value:T):T
}
let getDate:ConfigFn=function<T>(value:T):T{
return value;
}
getDate<string>('值value')
//另一種寫法
interface ConfigFn<T>{
(value:T):T
}
function getData3<T>(value:T):T{
return value;
}
var myGetData:ConfigFn<string> = getData3;
myGetData('值value')
myGetData(20)// REEOR
- 泛類
泛型可以幫助我們避免重復(fù)的代碼以及對(duì)不特定數(shù)據(jù)類型的支持
- 定義個(gè)類;
- 把類作為參數(shù)來(lái)約束數(shù)據(jù)傳入的類型
//操作數(shù)據(jù)庫(kù)的泛型類
class MysqlDb<T>{
add(info:T):boolean{
console.log(info);
return true;
}
}
//1.定義一個(gè)user類酷鸦,和數(shù)據(jù)庫(kù)進(jìn)行映射
class User{
username:string|undefined;
pasword:string|undefined;
}
let u=new User();
u.username='haha';
u.pasword="1234";
let Db=new MysqlDb();
Db.add(u);
symbols 和es6的一致 一種新的數(shù)據(jù)額類型
let sym2 = Symbol("key");
let sym3 = Symbol("key");
sym2 === sym3; // false, symbols是唯一的
//像字符串一樣饰躲,symbols也可以被用做對(duì)象屬性的鍵。
let sym = Symbol();
let obj = {
[sym]: "value"
};
console.log(obj[sym]); // "value"
// Symbols也可以與計(jì)算出的屬性名聲明相結(jié)合來(lái)聲明對(duì)象的屬性和類成員
const getClassNameSymbol = Symbol();
class C {
[getClassNameSymbol](){
return "C";
}
}
let c = new C();
let className = c[getClassNameSymbol](); // "C"
命名空間 namespace
// 相當(dāng)于一個(gè)自執(zhí)行函數(shù)
//定義一個(gè)namespace 暴露里邊的變量臼隔、函數(shù)等數(shù)據(jù)需要使用export導(dǎo)出嘹裂,不導(dǎo)出的外部無(wú)法使用
namespace Validation {
export interface StringValidator {//暴露類類型接口
isAcceptable(s: string): boolean;
}
const lettersRegexp = /^[A-Za-z]+$/;
const numberRegexp = /^[0-9]+$/;
export class LettersOnlyValidator implements StringValidator {//暴露一個(gè)類
isAcceptable(s: string) {
return lettersRegexp.test(s);
}
}
export class ZipCodeValidator implements StringValidator {//暴露一個(gè)類
isAcceptable(s: string) {
return s.length === 5 && numberRegexp.test(s);
}
}
}
new Validation.LettersOnlyValidator().isAcceptable("123");
let validators: { [s: string]: Validation.StringValidator; } = {};
validators["ZIP code"] = new Validation.ZipCodeValidator();
聲明合并
//1.合并接口
// 同名接口會(huì)合并、
// 同屬性接口必須類型一致摔握、
// 接口定義會(huì)被提升寄狼,合并也會(huì)被提前編譯、
// 使用合并后的接口必須包含所有的屬性氨淌、
interface Box {
height: number;
width: number;
}
let box1: Box = {height: 5, width: 6};//報(bào)錯(cuò) 跟代碼順序無(wú)關(guān)
interface Box {
height: number;
width: string;//同名屬性泊愧,類型不一樣,合并會(huì)報(bào)錯(cuò)
scale: number;
}
let box: Box = {height: 5, width: 6, scale: 10};
let box2: Box = {height: 5, width: 6};//報(bào)錯(cuò) 必須包含合并后接口的所有屬性
對(duì)于函數(shù)類型接口盛正,每個(gè)同名函數(shù)聲明都會(huì)被當(dāng)成這個(gè)函數(shù)的一個(gè)重載删咱。 同時(shí)需要注意,當(dāng)接口 A與后來(lái)的接口 A合并時(shí)豪筝,后面的接口具有更高的優(yōu)先級(jí)痰滋。
裝飾器decorators
能夠被附加到類聲明、方法续崖、屬性敲街、參數(shù)上
//裝飾器
function sealed(target) {
// target就是被裝飾的函數(shù)、類或者其他
}
@sealed
XXX類{
xxx
}
//等價(jià)于sealed(XXX類)
//裝飾器工廠
function color(value: string) { // 這是一個(gè)裝飾器工廠
return function (target) { // 這是裝飾器
// do something with "target" and "value"...
}
}
@color('res')
XXX類{
xxx
}
//等價(jià)于color('red')(XXX類)
//分類
//1.類裝飾器
@sealed
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
function sealed(constructor: Function) {
console.log(constructor)//Greeter
}
//2.方法裝飾器
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
@sealed
greet() {
return "Hello, " + this.greeting;
}
}
function sealed(target,fnName,desc) {
console.log(target)//函數(shù)本身
console.log(fnName)//函數(shù)名
console.log(desc)//函數(shù)描述
}
//3.屬性裝飾器
class Greeter {
@sealed
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
function sealed(target,attr) {
console.log(target)//實(shí)例對(duì)象
console.log(attr)//屬性名
}
//4.參數(shù)裝飾器
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet(@sealed g:string) {
return g + this.greeting;
}
}
function sealed(target,fnName,index) {
console.log(target)//實(shí)例對(duì)象
console.log(fnName)//函數(shù)名
console.log(index)//當(dāng)前參數(shù)的索引
}