TS学习笔记

140 阅读6分钟

一、TS开发环境搭建

1.下载安装node

2.使用npm指令全局安装ts

进入命令行
输入:npm i -g typescript

3.创建ts文件 4.使用tsc对ts文件进行编译

进入命令行
进入ts文件所在目录
执行命令:tsc xxx.ts

二、TS的类型声明

let a:number;
​
a = 1function sum(b:number, c:number):number{
​
    return b+c; 
    
}
​
let result = sum(20,30)

先给a指定类型,再赋值。同时函数也是如此;然后再进行编译

三、TS中的类型

//1.可以直接使用字面量来进行类型声明
let a: 10;
a = 10;
a = 20//这里会报错,因为不可重复赋值


//2.用"|"来表示或,即两个选项都可以,可重复赋值
let b: "男"|"女";
b = "男";
b = "女";


//3.同理可以同时声明两个类型
let c: number|string;
c = true;
c = 'hello';


//4.any表示的是任意类型,一个变量设置类型为any相当于对该变量关闭了TS的类型检测,不建议使用any
let d: any;
d = 1 ;
d = 'zyf';
d = true;


//5.声明变量如果不指定类型,则TS解析器会自动判断变量的类型为any(隐式的any)
let d;
d = 1 ;
d = 'zyf';
d = true;

//6.unknown表示未知类型
let e: unknown;
e = 10;
e = "hello";
e = true;

//7.d的类型是any,它可以赋值给任意变量(专门霍霍别人)
let f:string;
f = d;

//8.e的类型是unknown,它谁都赋值不了(内向),想要赋值的话需要加一个if判断语句
if(typeof e === "string"){
    s = e;
}

//9.类型断言,可以用来告诉解析器变量的实际类型
s = e as string;
s = e;

//10.类型断言的另一种写法
s = <string>e;

//11.void用来表示空,以函数为例,就表示没有返回值的函数
function fn(): void{
    return
}
function fn(): void{
    return undefind;
}
function fn(): void{
    return null;
}
//12.never表示永远不会返回结果
function fn2():never{
    
}
//never一般用来抛出错误
function fn2():never{
    throw new Errow('报错了')
}

//13.object表示一个js对象(指定范围太大了,用的比较少)
let a: object
a = {};
a = function(){
}
//常用的是:{},语法:{属性名:属性值,属性名:属性值}
let b: {name:string};
b = {name:'zyf'};

//14.在属性名后面加上?,表示属性是可选的
let b: {name: string, age?: number};
b = {name: 'zyf', age: 18};
        
let c: {name: string, age?: number};
c = {name: 'zyf'};
        
//15.[propName: string]:any 表示属性名为任意字符串的属性名,属性名类型为任意类型,任意属性名  	个数
let d: {name: string}, [propName: stirng]: any;
d = {name: 'zyf', age: 18, gender:'男', choose: false}
//当外面加了any后,属性名的类型为任意值,如果把any改为string,类型必须是string

//16.设置函数结构的类型声明,语法:(形参:类型, 形参: 类型) => 返回值
let e: (a:number, b: number) => number;
        
f = function(n1: string, n2: stirng): number{
    return 10;
}

//17.string[]和Array<stirng>表示字符串数组,number[]和Array<number>表示数值数组。
let e: string[];
let a: Array<string>
e = ['a', 'b', 'c'];
a = ['a', 'b', 'c'];
        
let f: number[];
let g: Array<number>;
f = [1,2,3];
g = [1,2,3];
        
//18.元组,元组就是固定长度的数组,语法:[类型,类型,类型]
let h = [string, number];
h = ['hello', 123]
//必须与声明的一一对应
        
//19.enum枚举
enum Gender{
    Male = 0,
    Female = 1
}
let i: {name: string, gender: Gender};
i = {
    name: '孙悟空',
    gender: 'gender.Male'
}
console.log(i.gender === 1)	
        
//20.&表示同时
let j: { name: stirng }&{ age:number };
j = { name:'zyf', age: 18};

//21.类型的别名,可以直接将myType的值或者类型赋给k和l
type myType = 1 | 2 | 3 | 4;
let k: myType;
let l: myType

四、编译选项

1、当ts文件进行编译时,可以在输出终端末尾加个 -w,这样可以随时监控ts的代码变化,并实时的更新编译后的js文件。如:tsc index.ts -w**

2、上述的方法只能监控一个文件,要是想监控多个文件可以新建个tsconfig.json(里面可以什么都不写),这样想监控多个文件就可以直接tsc -w

3、其中tsconfig.json里面可以添加一些配置

{
    /*
        tsconfig.json是ts编译器的配置文件,ts编译器可以根据它的信息来对代码进行编译
        
        "include"用来指定哪些ts文件需要被编译
        
        路径:**符号表示任意目录
            *表示任意文件
            
        "exclude"不需要被编译的文件目录
            默认值:["node_modules","bower_components","jspm_packages"]
    */
    
    "include":[
        "./src/**/*"
    ],
    "exclude":[
        "./src/hello/**/*"
    ]
}

五、类

类的简单应用

class Person{
    static name = 'zyf';
    age = 18; 
    readonly sex = 'male'
}
const per = new Person();
//通过实例对象调用类里面的属性
console.log(per.age)
//通过类名来调用里面的属性
console.logr(Person.name)
//报错,因为是静态方法,只能通过类名来调用
console.log(per.name)
//报错,因为sex为只读属性
per.sex = 'female'

构造函数

class Person{
    constructor(){
        console.log('hello')
    }
}
const per = new Person();

每当我们new一个对象时,construetor里的代码就会运行

六、抽象类

/*
    以abstract开头的类时抽象类
        抽象类和其他类区别不大,只是不能用来创建对象
        抽象类就是专门用来被继承的类
*/
abstract class Animal {
    name :string;
​
    constructor(name: string) {
        this.name = name;
    }
/*
    定义一个抽象方法
    抽象方法使用abstract开头,没有方法体
    抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
*/
    abstract sayHello() void
}
class Cat extends Animal{
    //因为上面定义的是一个抽象方法,所以这里继承的话必须要加上sayHello方法,对其进行重写
    sayHello(){
        console.log('喵喵喵');
    }
}

七、接口

1、接口中的所有属性都不能有实际的值

2、接口只定义对象的解构,而不考虑实际值

3、在接口中所有的方法都只是抽象方法

interface myInter{
    name: string;
    sayHello(): void;
}
/*
    定义类时,可以使类去实现一个接口,
    实现接口就是使类满足接口的要求
*/
class MyClass implements myInter{
    name: string;
    constructor(name: string){
        this.name = name
    }
    sayHello(){
        console.log('hello')
    }
}

定义接口就相当于定义了一个规范

八、属性的封装

public修饰的属性可以在任意位置访问 (修改),默认是public(不加修饰)

private私有属性,私有属性只能在类内部进行访问

-通过在类中添加方法使得私有属性可以被外部访问

protected受包含的属性,只能在当前类和当前类的子类中进行访问

claa Person{
    private name: string
    private age: number
    
    constructor(name: string,age: number){
        this.name = name
        this.age = age
    }
    setname(val){
        this.name = val
    }
    getname(){
        return this.name
    }
}
​
const per = new Person('zyf', 18)
per.setname('ls')
console.log(per.getname())
​

内部访问:类内部进行访问

外部访问:类外部进行访问,如per.name = 'ls'

九、泛型

function fn<T, K>(a: T, b: K): T{
    console.log(b);
    return a;
}
fn<number, string>(a: 123, b: 'hello');
​
interface Inter{
    length:number;
}
//T extends Inter表示泛型T必须是Inter实现类(子类)
/*
  实现类就是实现接口中约定的内容。
  意思是说,接口中定义规范,实现类来确定规范如何运行的。比如接口定义一个Person接口,定义了一个    eat方法,这个吃的方法是空的。
  那需要一个实现类比如ZhangSan类实现了Person接口,就必须要给定eat方法的具体实现,说明张三是    如何吃的。
*/
function fn1<T extends Inter>(a: T): number{
    return a.length;
}