typeScript

57 阅读6分钟

ts是js的超级,在满足所有的js语法基础上,又增加了类型判断等特性,通过tsc编译成我们想要的js版本。

1. 类型声明

image.png

2. 字面量和联合类型

image.png

3. any(建议尽量避免)
隐式的any类型
let a;
a = 10;
a = 'str';
a = true;
隐式的定义变量并声明类型
let b = 10;
4. unknown(未知类型, 类型安全的any)
any类型可以赋值给任意变量
let a: any;
let b = 'string';
b = a;
b = true;
所以不建议使用any, 而是用unknown;
unknown类型不可以赋值给任意变量
解决办法:
let c: unknown;
let d: string;
c = 'hello';
d = c as string; // 类型断言
或者
d = <string>c; // 类型断言
5. void

函数没有返回值的时候用

function a(): void{
    return;
    或者
    return undefined 或者 return null;
}
6. never

永远不会有返回值, 空是有值的, 值为空, 所以不能用never

function a(): never{
   throw new error("这种是没有返回值...")
}
7. object
let a: { name: string, age?: number }; // age?: age属性就是可选的了, 有可以, 没有也可以
a = { name: 'ths' };
b: a = { name: 'ths', age: 18 };
let c: { name: string, [propName: string]: any } // [propName: string]可以定义多个不确定的属性
c = { name: 'ths', age: 18, sex: 20, isTrue: false };
let d: (a: number, b: number) => number;
d = function(num1, num2): number{
    return num1 + num2;
} 
8. array
let arr1: string[];
let arr2: Array<number>;
let arr3: Array<any>;
9. tuple(元组, 元组就是长度固定的数组, 最好不要太长, 太长不如用数组了)
let tarr: [string, number];
tarr = ['str', 123];
10. enmu(枚举: 把所有的可能的情况都列出来)
enmu Sex{
    Male,   // 不写值的话, 自动转成0
    Female = 1  // 赋值为1
}
let i: { name:  string, sex: Sex };
i = {
    name: 'ths',
    sex: Sex.Male // 自动转成0了
}
11. | 和 & (联合类型和与类型)
let a: string | number;
a = 'ths';
a = 18;
let b: { name: 'string' } & { age: number };
b  = { name: 'ths', age: 20 };
12. type(类型别名)
type myType = 1 | 2 | 3 | 4 | 5;
let k: myType;
let h: myType;
k = 1;
h = 5;
// 当前用法与字面量一样的效果
13. ts编译选项
1. include指定需要编译的文件: ["./src/**/*"] (src: src目录下  **: 任意目录  *: 任意文件)
2. exclude排除不需要编译的文件: ["./src/assets.....自己写"] (默认值: ["node_modules", "bower_components", 
"jspm_packages"])
3. files: [ ... 文件名 ]: 只有文件少的时候, 用一个数组来统计编译的文件就行了
4. "compilerOptions":{
    "target": "es5" // 指定编译的版本  es3  es5  es6 es2015 es2016... es2020 esnext
    "module": "es6" // 指定要使用的模块化的规范  none commonjs amd system umd es6 es2015 es2020 esnext
    "lib": ["dom", "dom.iterable", "esnext"] // 指定项目中用到的库 es6 promise...
    "outDir": "./dist" // 指定输出目录
    "outFile": "./dist/app.js" // 将代码合并为一个文件
    "allowJs": false // 是否对js文件进行编译, 默认为false
    "checkJs": false // 是否检查js语法符合规范, 默认为false
    "removeComments": true // 是否移除注释, 默认为false
    "noEmit": false // 不生成编译后所产生的js文件, 默认为false
    "noEmitOnError": false // 报错时不生成编译文件, 默认为false
    "awaysStrict": false // 设置编译后的文件是否使用严格模式, 默认为false
    "noImplicitAny": false // 不允许隐式的any类型设置, 默认为false
    "noImplicitThis": false // 不允许不明确类型的this, 默认为false
    "strictNullChecks": false // 严格的检查空值, 默认为false
    "strict": 所有的检查的总开关, 如果设置为true, 所有的都打开了就不用写了
}
14. calss 类
class Person{
    name: string; // 只能创建对象在对象身上进行访问
    static age: number; // 静态属性: 不用new对象就可以被类访问的属性 Person.age
    readonly sex: string; // readonly: 只读属性
    say(){
        console.log('...')
    }
}
15. 构造函数和this
class Dog{
    name: string;
    age: number;
    constructor(name: string, age: number){
        this.name = name;
        this.age = age;
    }
    bark(){
        console.log("汪汪汪!");
    }
}
const dog = new Dog('小黑', 18);
16. extends 继承
class Animal{
    name: string;
    age: number;
    constructor(name: string, age: number){
        this.name = name;
        this.age = age;
    }
    say(){
        console.log("动物在叫!");
    }
}
class Dog extends Animal{ // 继承后字类将会有父类的所有属性和方法
    run(){
        console.log("小狗边跑边叫!");
    }
}
class Cat extends Animal{ // 继承后字类将会有父类的所有属性和方法
    say(){ // 方法的重写: 子类会覆盖符类中的say方法
        console.log("小猫喵喵喵!");
    }
}
new dog = new Dog("小黑", 18);
dog.run();
17. super 关键字
class Animal{
    name: string;
    constructor(name: string, age: number){
        this.name = name;
    }
    say(){
        console.log("动物在叫!");
    }
}
class Dog extends Animal{ // 继承后字类将会有父类的所有属性和方法
    age: number;
    constructor(name: string, age: number){ // name是来自父类的
        // 如果在字类中写了构造函数, 父类的构造函数就因为重写不会执行了, 所以需要super去调用父类中的构造函数
        super(name); // 调用父类的构造函数, name是来自父类的
        this.age = age;
    };
    say(){
        super.say(); // super: 其实就是父类 super.say()就是调用父类的say方法
    }
}
const dog = new Dog('小黑', 18);
18. abstract 抽象类
abstract class Animal{ // 抽象类: 专门用来给别人继承的, 没有其他作作用, 不能创建对象
    name: string;
    constructor(name: string, age: number){
        this.name = name;
    }
    abstract say(): void; // 抽象方法, 必须被字类重写
}
class Dog extends Animal{
    // 抽象方法重写
    say(){
        super.say();
    }
}
const dog = new Dog('小黑');
dog.say();
19. interface 接口
// 接口用来定义一个类或者对象包含哪些属性和结构
interace myInterface{
    name: string; // 接口中所有的属性不能赋值
    say(): void; // 不能有方法体, 接口只定义对象的结构而没有实际的值, 类似抽象方法
}
interace myInterface{ // 接口可以重名
    age: number;
}
// 接口也可以当成类型的声明去使用, 声明类型的用法与type别名类似
let myInter: myInterface = {
       name: 'ths',
       age: 18,
       say(): void 或者 say(){ console.log('11111')};
}
/* 定义类时, 可以用类去实现一个接口, 用到关键字 implements
接口其实对类进行了限制,与抽象类很像,区别在于抽象类中可以有抽象方法也可以有其他的,
接口内只能有抽象方法
另外的区别在于使用抽象类时使用extends, 接口使用implements*/
calss MyClass implements myInterface{
    name: string;
    age: number;
    constractor(name: string, age: number){ // 类实现接口必须定义构造函数
        this.name = name;
        this.age = age;
    }
    say(){
        console.log('类实现接口');
    }
}
19. 属性的封装
class Animal{
    public name: string; // 公共的, 都能访问
    private age: number; // 私有的, 只能在当前类内部访问 producted: 只能在当前或其字类访问,不能在实例访问
    constructor(name: string, age: number){
        this.name = name;
        this.age = age;
    }
    getAge(){
        return this.age;
    }
    setAge(value: number){
        this.age = value;
    }
}
const animal = new Animal('小狗', 18);
animal.getAge();
animal.setAge(20);

属性存取器的用法: 用来对赋值方法进行限制, 方法内可以做条件判断

class Animal{
    public name: string;
    private age: number;
    constructor(name: string, age: number){
        this.name = name;
        this.age = age;
    }
    get age(){ // 属性存取器
        return this.age;
    }
    set age(value: number){
        if(value > 0){ // 增加条件, 年龄必须大于0
               this.age = value;
        }
    }
}
const animal = new Animal('小狗', 18);
console.log(animal.age); // 实际是调用了get age()方法, 用起来和属性一样;
animal.age = 30; // 实际是调用了set age()方法, 用起来和属性一样;

构造函数特殊写法

class C {
    constractor(public name: string, public age: number){
        // 此时构造函数内就可以省略: this.name = name;  this.age = age;
    }
}
20. 泛型

在定于一个函数或者类时, 如果遇到不确定类型就可以用泛型

fucntion fn(a: any): any{
    return a;
}
function fn<T>(a: T): T{ // 泛型的好处, 不确定类型, 同时避免了any的类型检查跳过性
    return a;
}
fn(10); // 实际为fn(a: 10);  调用后传入number, 自动判断返回值类型也为number;
fn<string>('hello'); // 实际为fn(a: 'hello') 如果实际特别复杂判断不出来, 可以手动指定类型
function fn2<T, K>(a: T, b: K): T{// 可以指定多个泛型
    return a;
}
interface Inter{
    length: number;
}
function fn3<T extends Inter>(a: T): number{//表示泛型T必须是Inter实现类(子类),不一定非得传接口
    return a.length;
}
class MyClass<T>{ // 泛型在类中的使用方法
    name: T;
    constractor(name: T){
        this.name = name;
    }
}
const mc = new MyClass<string>("可以手动指定类型!");