typescript的基本语法

typescript

typescript 是js的超集,静态类型检测

命令:

//监听ts文件的变化
$ tsc -p tsconfig.json --watch

原始类型

为了使文件里的变量不污染全局

//在第一行增加
export {};

string

let str:string = "2" //string

number

let num:number = 1 //number

boolean

let bool:boolean = true  //boolean

null

let nul:null = null; // null

undefined

let undef: undefined = undefined; // undefined

symbol

let sy: symbol = Symbol(); // symbol

void

let vd: void = undefined; // 可以把undefined类型赋值给void类型,但是反过来不行
// 函数没有返回值,那么函数的返回值类型就是voidfunction fn(): void {return undefined;
}

非原始类型

object

不能是string,number,boolean,symbol,严格模式:多包括null,undefined

let obj7:object = {a: 1, b: '2'};//对象
let obj8:object = [1, 2, 3]; //数组

Object

Object是object类型子类型

包含了原始类型和非原始类型

代表所有拥有 toString、hasOwnProperty 方法的类型,所以所有原始类型、非原始类型都可以赋给 Object,严格模式下不包括null,undefined。{}空对象类型和大 Object 一样。

let a5:Object = 1
let a6:Object = []
let a7:Object = {}
let a8:Object = function(){}

{ }

{ }和Object范围类型一样

let a9:{} = 1
let a10:{} = [1,2,3]
let a11:{a:number,b:string} = {a:1,b:"1"}
let a12:{} ={}

数组类型

定义数组的方式

方式一:直接定义

let arr :number[] = [1,2,3]
arr[3] = 4

方式二:元组

// 元组:固定元素长度的数组,用数组的方式可以拓展
let arr1:[number,string,boolean] = [1,"2",true]
// arr1[3] = 3  //报错
arr1.push(2)

方式三:Array接口类型::泛型,类型参数化

Array<类型>
//例如:
let arr1: Array = [1, 2, 3];
arr1.push('3'); // 报错
arr1.push(5);
let arr2: string[] = ['4', '5', 'a'];
arr2[3] = '6';let arr3:Array<{}> = [1,"1",true]
let arr4:Array = [1,"1",true]
 
字面量类型
const 
//定义的不可以修改const a11:1 = 1
let  str:"2" = "2"
// let  str1:"2" = "1"   //报错
let bool:true = true

TypeScript 支持 3 种字面量类型:string字面量类型、number字面量类型、boolean字面量类型

联合类型 |

用 | 表示可能的类型

let arr:(number | string | boolean)[] = [1,"2",true]let a:number|string = 1;
a = "2"

交叉类型 &

用 & 表示 必须拥有全部

let a2:number & string //既要满足number类型,也要满足string类型的值 (没有一个这样的值)
let obj:{age:number} &{name:string} = {age:12,name:"张三"}

组合

let obj1:({age:number} | {height:200}) & ({name:string} | {wight:400}) = {age:200,name:"张三"
}obj1={age:160,name:"李四",height:200
}

any

指的是一个任意类型,它是官方提供的一个选择性绕过静态检测的作弊方式。非常不建议使用: (any是地狱)

let a:any =1;
a="2"
a={}
a.toFixed(1)

unknown

unknown 是typeScript 3.0中添加的一个类型,它主要用来描述类型并不确定的变量,和any的区别就是会进行类型检测。

let b:unknown;
b=1;
b="2";
b=undefined;
b={};// b.toFixed(1)//报错,因为此时b的类型不确定

as 断言

// as 断言,确定b的类型
(b as number).toFixed(1)

never类型

never表示永远不会发生值的类型

function throwErrFn():never {throw new Error('出错了');
}//   	1. **如果函数里是死循环,返回值类型也是never **
//   	2. **never 是所有类型的子类型

接口 interface

定义一个类型

interface PersonInfoItf {name:string;age:number;[key:string]:number | string;
}
let obj:PersonInfoItf={name:"",age:12}
let obj1:PersonInfoItf={name:"111",age:12}
let obj2:PersonInfoItf={name:"",age:12,a:1}

定义一个数组

let arr:(number| string)[] = [1,2,3,"4"]interface ArrItf {[idx:number] : number | string
}
let arr1:ArrItf = [1,2,3,"4"]

定义没有固定属性的对象接口类型

interface ObjItf{[key :string] : string | number
}
let arr2:ObjItf = {a:1,b:2,c:3
}

定义函数类型

let fn:() => void = ():void => {console.log(11)
}interface FnItf {(a: string):void
}
let fn1:FnItf = (a):void => {console.log(11)
}//**很少使用接口类型来定义函数的类型,更多使用内联类型或类型别名配合箭头函数语法来定义函数类型;**

接口继承

多个不同接口之间是可以实现继承的,但是如果继承的接口PersonInfo和被继承的接口NameInfo有相同的属性,并且类型不兼容,那么就会报错。

多个接口组合成一个新的接口

interface PersonInfoItf{name:string
}interface OtherInfoitf {age:number
}interface MaleItf extends PersonInfoItf,OtherInfoitf{}let person:MaleItf = {name:"",age:12
}

多个相同的接口

多个相同接口,相同名字的接口类型,里面的属性会进行合并

interface A {name:string
}
interface A {age :number// name:number ; //报错,上面已经定义了
}let a :A = {name:"",age:12
}

用处:扩展第三方库的接口

可缺省和只读属性修饰

可缺省:用 ?表示

只读:用 readonly 表示,写在只读的属性前面

interface B {readonly name:string;age?:number
}let b:B = {name:""} //age 可缺省,有没有都行
// b.name = "123"//报错 ,因为name属性只读let c:B = {name:"",age:12}

类型别名

interface接口类型不支持联合类型和交叉类型

类型别名 type 类型名 = 具体类型值

type ThreeTypes = string | number | boolean;
let a:ThreeTypes = 1
let b:ThreeTypes = "1"
let c:ThreeTypes = truetype PersonType = {name:string} & {age :number}
let a1:PersonType = {name:"",age:12
}

用处或者用法:类型别名可以针对接口没法覆盖的场景,例如组合类型、交叉类型等;

// 类型别名是不能拿重名
// type ArrType = Array //报错 重名了
type ArrType = {[idx:number]:number | string}// 函数定义
type Fntype = () =>number
let fn:Fntype = ()=>{return 1}
let fn1:() =>number = ()=>{return 1}

函数类型

函数类型定义

function fn():undefined{return undefined}
function fn1():void{};
function fn2(a:string,b:number):void{}

接口定义函数类型

interface FnItf{(a:string,b:number):void
}// let fn3:FnItf = (a,b) =>{}//a 和 b 代表的是参数
let fn3:FnItf = (b,a) =>{}

类型别名定义函数类型

type Fntype = ()=>{name:string}
let fn4:Fntype=()=>({name:""})

声明函数类型

declare function fn5():void;

函数的参数类型

// ?可选参数  意思是不传
function fn(a:string,b?:number){}
fn("",1)
fn("")
// fn()//报错// 设置函数参数默认值
function fn1(str:string="123"){}
fn1()
fn1("123456")// 剩余参数
// 解构
function fn2(...arr:number[]){}
fn2(...[1,2,3])
fn2(1)
fn2(1,2,3,4,5)

this

在Typescript中,必须要明确的指定this的类型(严格模式下)。

type ObjType = {name:string};function fn(this:ObjType,a:string){console.log(this);}let obj:ObjType = {name:""};
// fn.apply({})//报错  { } 值不符合ObjType的类型
fn.apply({name:""},[""])
fn.apply(obj,[""])

枚举

枚举的作用在于定义被命名的常量集合,一个默认从 0 开始递增的数字集合,称之为数字枚举。也可以指定值,这里可以指定的值可以是数字或者字符串。

enum StatusCode{NotLogin = -1,Success,Exprie
}
//自动会补全+1 number类型// 假设后端返回的状态码是变量res
let res:number = 0;if(res===StatusCode.NotLogin){console.log("没登录");
}else if(res===StatusCode.Success){console.log("登录成功");  
}else if(res===StatusCode.Exprie){console.log("登录已过期");  
}console.log(StatusCode.Success,StatusCode.Exprie);

泛型

指的是类型参数化,即将原来某种具体的类型进行参数化。

let arr:Array<number | boolean | string> = [1,true,""]let arr1:Array<number>=[1];
function fn(a:unknown){}
fn(1)
fn("")
fn(true)function fn1(p:number):number{return p
}
function fn2(p:string):string{return p
}
function fn3(p:boolean):boolean{return p
}type parmsType = number | string | boolean;function fn5(p:parmsType):parmsType{return p
}

泛型函数定义

function fnn<S,P=string>(p:P,s:S):P{return p
}fnn<number>("",1)
fnn<string>("","")type ObjType = {n:string}
fnn<ObjType,number>(1,{n:""})
fnn("","")// fnn(p: "", s: string): ""

泛型类型

// 定义数组类型
let arr: Array<number> = [1];
let arr1: Array<string> = [""];// 类型别名
type typeFn<P> = (params: P) => P;
let fntype: typeFn<number> = (n: number) => {return n;
};let fn1:typeFn<string> = (p: string):string => {return p;
} 
// 定义接口类型
interface TypeItf<P> {name: P;getName: (p: P) => P;
}let t1: TypeItf<number> = {name: 123,getName: (n: number) => {return n;},
};let t2: TypeItf<string> = {name: "123",getName: (n: string) => {return n;},
};

泛型约束

把泛型入参限定在一个相对更明确的集合内,以便对入参进行约束。

// T只接受number & string
interface ObjItf<T extends string | number> {name:T;getName:(n:string)=>string
} let obj:ObjItf<number> ={name:1,getName:(n:string)=>{return n}
}

类的定义使用

// 在定义类的同时,除了定义的这个类,也创建了一个接口,接口的名字就是类名Personclass Person{// 成员属性:类型name:string="张三"
}let p:Person = new Person();
let obj:Person={name:""
}class Male {name:string;age:number;constructor(name:string ,age:number){this.name = name;this.age = age}say(this:Male,song:string){console.log(song);return this}
}let m = new Male("张三",20)
console.log(m.say("唱歌").name);
console.log(m.name,m.age);let m1 = new Male("李四",100)
console.log(m1.say("跳舞").name);
console.log(m1.name,m1.age);

继承

使用extends关键字实现继承

// 类中常用修饰符
// public:公用的,默认类中的属性和方法都是public修饰的,基类,子类,类外部都可以访问
// protected:受保护的,基类,子类都可以访问,类外部不可以访问
// private:私有的,基类可以访问,子类,类外部都不可以访问
// readonly:只读(不能修改)class Person{public name:string;protected readonly weight:string="50kg";private heigth:string = "150";constructor(name:string){this.name = name}say(){// this.weight = "" ;只读属性不能被修改// 可以在当前的类中访问自己的public修饰的成员属性console.log(this.name,this.weight,this.heigth);}
}let p = new Person("张三")
p.say()
console.log(p.name);
// 受保护和私有的属性不能在类的外部访问,p.weightclass Male extends Person{age:number;constructor(name:string,age:number){super(name);this.age = age}say(): void {console.log("子类"+ this.name + this.weight);// 子类不能访问父类的private修饰的属性}
}let m = new Male("李四",22)
console.log(m.name,m.age);

静态属性

基于静态属性的特性,往往会把与类相关的常量、不依赖实例 this 上下文的属性和方法定义为静态属性,从而避免数据冗余,进而提升运行性能。

class Person{name!:string;// 静态成员static readonly age:number = 10;
}let p = new Person();
console.log(p.name);
// 访问静态成员
console.log(Person.age);

抽象类和接口

抽象类,它是一种不能被实例化仅能被子类继承的特殊类。

abstract class Person1{abstract name:string;abstract say():void;run(){console.log("跑");}
}class Male extends Person1{name: string = "zhsngan";say(): void {console.log("抽象方法say");}
}let m = new Male();
m.name;
m.say();
m.run();// 接口
interface Person2{name:string;age:number;say:()=>void
}class Female implements Person2{name: string = "";age: number= 20;weight:string = "200"say(){}
}
// class F1 implements Person2 {
//     name: string;
//     age: number;
//     say: () => void;// }

修饰符

public、private、protected、readonly

在 TypeScript 中就支持 3 种访问修饰符,分别是 public、private、protected。通过这三个修饰符做到控制属性和方法的访问。

  • public:基类、子类、类外部都可以访问;
  • protected:基类、子类可以访问,类外部不可以访问;
  • private:基类可以访问,子类、类外部不可以访问;
  • readonly:只读修饰符
class Person {public readonly name: string = '张三';protected age: number = 20;private height: string = '180';protected getPersonInfo():void {console.log(this.name, this.age, this.height); // 基类里面三个修饰符都可以访问}
}class Male extends Person {public getInfo():void {console.log(this.name, this.age); // 子类只能访问public、protected修饰符的}
}let m = new Male();
console.log(m.name); // 类外部只能访问public修饰的
m.name = '李四'; // name属性使用只读修饰符,所以不能对name进行赋值修改操作

工具类型

Required:必填

Readonly:只读

extends: 约束

keyof:提取对象属性名、索引名类型

in :类型映射

typeof : 提取变量类型

interface PersonItf{name:string;age?:number;
}// interface PersonItf1{
//     name:string;
//     age:number;
// }// 重复了// Required:必填
type PersonItf1 = Required<PersonItf>// Readonly:只读
type PersonItf2 = Readonly<PersonItf>// extends: 约束
type TypeFn<P> = P extends string | number ?P[]:P;
let a1:TypeFn<string> = ["111"];  //a1类型:string[]
let a2:TypeFn<boolean> = true;  //a1类型:string[]// infer:类型推断
type TypeFn1<T> = T extends {name:infer N;age:infer A} ?[N,A]:[T]
let a3:TypeFn1<{name:string,age:number}> = ["",2]
let a4:TypeFn1<boolean> = [false]// keyof:提取对象属性名、索引名类型
interface ObjItf{name:string;age:number;// [idx:number]:number;[key:string]:string | number;
}type TypeKeyof = keyof ObjItf //"name" | "age" | string | numberlet a1:TypeKeyof="name"
a1=2
a1=""// in :类型映射
type numAndStr = number | stringtype ObjType1 = {[key in numAndStr]:numAndStr}
let ob1:ObjType1 = {name:"",1:2
}// keyof in 组合使用 "name" | "age" | string | number
type Required<T> = {[P in keyof T]-?:T[P]}
type ItfType =  Required<ObjItf>// typeof : 提取变量类型
let a2 =1;
type TypeA2 = typeof a2let obj2 = {name:"",age:20
}type ObjType2 = typeof obj2;let obj3:ObjType2 = {name:"",age:10
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章