ts语法概览

作者: 海豚先生的博客 | 来源:发表于2023-02-28 10:02 被阅读0次

    ts对应js的数据类型

    let name: string = "bob";
    let age: number = 37;
    let isDone: boolean = false;
    let u: undefined = undefined;
    let n: null = null;
    let obj: object = {x: 1};
    let bigLiteral: bigint = 100n;
    let sym: symbol = Symbol("me");

    Array

    // 元素类型[]
    let list: number[] = [1, 2, 3];
    // Array<元素类型>
    let list: Array<number> = [1, 2, 3];
    
    interface MyObject {
       name: string;
       age: number;
    }
    
    let arr: MyObject[] = [{name: "兔兔", age: 18}] // OK
    复制代码
    

    Tuple

    • 对于内部不同类型的数组可以使用元组类型来定义
    • 注意,元组类型只能表示一个已知元素数量和类型的数组,长度已指定,越界访问会提示错误。例如,一个数组中可能有多种类型,数量和类型都不确定,那就直接any[]。
    let x: [string, number];
    
    x = ['hello', 10]; // OK
    x = [10, 'hello']; // Error
    

    undefined和null

    • 默认情况下null和undefined是所有类型的子类型。 就是说你可以把null和undefined赋值给任何类型的变量。

    void

    • void表示没有任何类型,和其他类型是平等关系,不能直接赋值
    • 一般也只有在函数没有返回值时去声明

    any和unknown

    • any(既是top type又是bottom type)会跳过类型检查器对值的检查,任何类型的值可以赋值给any,同时any类型的值也可以赋值给任何类型
    • 所有类型都可以分配给unknown(top type),但它只能赋值给unknown和any

    never

    • never类型表示的是那些永不存在的值的类型。
    • 比如函数执行时抛出异常或者函数中的死循环,不存在返回值
    • 是任何类型的子类型,也可以赋值给任何类型,但没有类型可以赋值给never类型

    as 类型断言

    • 类型转换通常发生在你比TS更了解某个值的详细信息的时候。
    // as 语法
    let someValue: any = "this is a string";
    let strLength: number = (someValue as string).length;
    

    !

    跳过ts校验,保证有值

    // 断言event.target有值,不为null/undefined
    const a:string = event.target!.name
    

    类型推论

    • 如果没有明确的指定类型,那么 TypeScript 会依照类型推论的规则推断出一个类型。
    let myFavoriteNumber = 'seven';
    myFavoriteNumber = 7; // Error
    

    | 联合类型

    • 联合类型表示取值可以为多种类型中的一种,使用 | 分隔每个类型
    let myFavoriteNumber: string | number;
    myFavoriteNumber = 'seven'; // OK
    myFavoriteNumber = 7; // OK
    

    & 交叉类型

    • 交叉类型是将多个类型合并为一个类型
    • 如果key相同但是类型不同,则该key为never类型。
    interface A {
      name: string,
      age: number
    }
    interface B {
      name: string,
      gender: string
    }
    
    let a: A & B = { // OK
        name: "兔兔",
        age: 18,
        gender: "男"
    };
    

    interface 接口

    • 定义一些参数,规定变量里面有什么参数,参数是什么类型,使用时就必须有这些对应类型的参数,少或者多参数、参数类型不对都会报错
    interface LabeledValue {
      label: string;
      money?: number; // 可选属性
      readonly x: number; // 只读属性
      [key: string]: any; // 索引签名,TypeScript 支持两种索引签名:字符串和数字。
    }
    function printLabel(labeledObj: LabeledValue) {
      console.log(labeledObj.label);
    }
    // myObj中的属性会进行类型推论,以此绕过多余的类型检查
    let myObj = { size: 10, label: "Size 10 Object" };
    printLabel(myObj); // OK
    

    ReadonlyArray

    • 数组创建后再也不能被修改
    let a: number[] = [1, 2, 3, 4];
    let ro: ReadonlyArray<number> = a;
    ro[0] = 12; // Error
    ro.push(5); // Error
    ro.length = 100; // Error
    
    a = ro; // Error
    a = ro as number[]; // OK
    

    extends 接口继承接口

    • 接口可以多继承。
    • 使用多继承时,先确保父接口没有共有属性,或共有属性定义的类型都相同。
    interface Shape {
      color: string;
    }
    interface PenStroke {
      penWidth: number;
    }
    interface Square extends Shape, PenStroke {
      sideLength: number;
    }
    
    let square: Square = { sideLength: 1 } // Error
    let square1: Square = { sideLength: 1, color: 'red' } // Error
    let square2: Square = { sideLength: 1, color: 'red', penWidth: 2 } // OK
    

    Pick 选择性继承

    • 主要是从一个已知的类型中,取出子集,作为一个新的类型返回
    // 原始类型
    interface TState {
        name: string;
        age: number;
        like: string[];
    }
    // 如果我只想要name和age
    interface TSingleState extends Pick<TState, "name" | "age"> {};
    或者
    interface TSingleState extends Pick<TState, "name" | "age"> ;
    

    函数声明

    // 剩余参数
    function sum(x: number, y: number, ...rest: any[]): number {
        return x + y;
    }
    

    函数表达式

    // 可选参数、参数默认值
    let mySum: (x: number, y: number, m:number = 11, z?: number) => number = function (x: number, y: number): number {
        return x + y;
    };
    

    用接口定义函数类型

    interface SearchFunc{
      (source: string, subString: string): boolean;
    }
    
    let mySearch: SearchFunc = function(source: string, subString: string) { // OK
      let result = source.search(subString);
      return result >-1;
    };
    

    内置对象

    let s: String = new String('兔神');
    let n: Number = new Number(123);
    let b: Boolean = new Boolean(1);
    let e: Error = new Error('Error occurred');
    let d: Date = new Date();
    let r: RegExp = /[a-z]/;
    
    let body: HTMLElement = document.body;
    let allDiv: NodeList = document.querySelectorAll('div');
    document.addEventListener('click', function(e: MouseEvent) {
      // Do something
    });
    
    function sum() {
        let args: IArguments = arguments; // 类数组对象
    }
    
    

    type 类型别名

    • 类型别名就是给一种类型起个别的名字,使用type关键字来定义
    type StringType = string;
    let str: StringType;
    str = 'hello';
    str = 123 // Error
    

    import type ... from & export type ... from

    导入或者导出类型文件,编译器将把这些类型文件删除

    • import type ... from — 让编译器知道您要导入的内容绝对是一种类型。
    • export type ... from — 一样, 仅用作导出。
    
    // src/lib-type-re-export.ts
    export type { Track, Playlist } from "./types"; // 类型文件
    export type { CreatePlaylistRequestParams } from "./api"; // 类型文件
    export { createPlaylist } from "./api";
    
    // 会被编译为:
    
    // dist/lib-type-re-export.js
    export { createPlaylist } from "./api";
    

    字符串字面量类型

    • 字符串字面量类型用来约束取值只能是某几个字符串中的一个。
    type Name = 'ALisa' | 'Bob' | 'Cola'
    
    let name: Name = 'Alisa'; // Error 与 DOM 中的全局 window 对象下的 name 属性出现了重名
    let name1: Name = 'ALisa'; // OK
    let name2: Name = 'Bob'; // OK
    let name3: Name = 'Cola'; // OK
    let name4: Name = '兔兔'; // Error
    

    Enum 枚举

    • 枚举是一个被命名的整型常数的集合
    • TS支持数字的和基于字符串的枚举。
    // 数字枚举
    enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
    console.log(Days.Sun) // 0
    console.log(Days.Mon) // 1
    // 初始化枚举成员,那么该初始化成员后面的成员会在它的基础上自动增长1
    enum Days {Sun = 1, Mon, Tue, Wed, Thu, Fri, Sat};
    console.log(Days.Sun) // 1
    console.log(Days.Mon) // 2
    
    // 字符串枚举
    enum Direction {
        Up = "UP",
        Down = "DOWN",
        Left = "LEFT",
        Right = "RIGHT",
    }
    // 异构枚举,枚举可以混合字符串和数字成员
    enum Direction {
        name = '兔兔',
        age = 18
    }
    

    class 类

    class Animal {
        // public 修饰符,类的属性、方法可以在外部访问
        public static age: number = 18;
        // 类的属性、方法不可以在外部访问
        private static title: string = '兔兔';
        // protected 修饰符,在派生类中仍然可以访问(继承中可以访问)
        protected title: string = '兔兔';
        class Animal {
        constructor(public name: string, private age: number, protected sex: string) {
        
        }
    }
    
    Animal.age; // OK
    Animal.title; // Error
    

    abstract 抽象类

    • 象类做为其它派生类的基类使用, 不允许被实例化。
    • 抽象类中的抽象方法不包含具体实现并且必须在派生类中实现
    abstract class Department {
        constructor(public name: string) {
        }
        printName(): void {
            console.log('Department name: ' + this.name);
        }
        abstract printMeeting(): void; // 必须在派生类中实现
    }
    class AccountingDepartment extends Department {
        constructor() {
            super('Accounting and Auditing'); // 在派生类的构造函数中必须调用 super()
        }
        printMeeting(): void {
            console.log('The Accounting Department meets each Monday at 10am.');
        }
        generateReports(): void {
            console.log('Generating accounting reports...');
        }
    }
    let department: Department; // OK:允许创建一个对抽象类型的引用
    department = new Department(); // Error: 不能创建一个抽象类的实例
    department = new AccountingDepartment(); // OK:允许对一个抽象子类进行实例化和赋值
    department.printName(); // OK
    department.printMeeting(); // OK
    department.generateReports(); // Error: 方法在声明的抽象类中不存在
    复制代码
    

    implements 类实现接口

    • 用类去实现接口
    interface Age {
      age: number;
    }
    
    interface Title{
      title: string;
    }
    class title implements Title, Age{
      title: string = '兔兔';
      age: number = 18;
    }
    

    T 泛型

    • 泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
    // 泛型函数
    function identity<T>(arg: T): T {
        return arg;
    }
    identity<number>(1); // OK:明确的指定`T`是`number`类型
    identity(1); // OK:让编译器自己推断类型
    
    // 泛型约束,在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法。
    function loggingIdentity<T>(arg: T): T {
        console.log(arg.length); // Error
        return arg;
    }
    function loggingIdentity<T>(arg: T[]): T[] {
        console.log(arg.length);  // OK
        return arg;
    }
    
    // 泛型接口
    interface Person<T> {
        name: T;
        getAge(arg: T): T;
    }
    
    let myIdentity: Person<string> = {
        name: "兔兔",
        getAge(name) {
            return name
        }
    };
    
    // 泛型类
    class GenericNumber<T> {
        zeroValue: T;
        add: (x: T, y: T) => T;
    }
    let myGenericNumber = new GenericNumber<number>();
    
    // 泛型参数的默认类型
    function createArray<T = string>(length: number, value: T): Array<T> {
    }
    

    类型守卫

    // 要定义一个类型守卫,我们只要简单地定义一个函数,它的返回值是一个类型谓词
    function isA(person: A | B): person is A{
        return(person as A).name !== undefined;
    }
    
    // 使用
    function doSomething(person: A | B): void {
        if(isA(person)) { // OK
            // ...
        }
    }
    
    // 使用in操作符
    // typeof类型守卫
    // instanceof类型守卫
    // 
    

    相关文章

      网友评论

        本文标题:ts语法概览

        本文链接:https://www.haomeiwen.com/subject/rvbhldtx.html