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类型,但是反过来不行
// 函数没有返回值,那么函数的返回值类型就是void

function 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 = true

type 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
    }
}

类的定义使用

// 在定义类的同时,除了定义的这个类,也创建了一个接口,接口的名字就是类名Person

class 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.weight

class 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 | number

let a1:TypeKeyof="name"
a1=2
a1=""


// in :类型映射
type numAndStr = number | string

type 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 a2

let obj2 = {
    name:"",
    age:20
}

type ObjType2 = typeof obj2;

let obj3:ObjType2 = {
    name:"",
    age:10
}

你可能感兴趣的:(html,css,前端,typescript)