• TypeScript 安装使用及基本类型


    TypeScript

    下载

    npm install -g typescript

    查看

    tsc -v

    初始化 tsconfig.json

    tsc --init

    运行

    tsc xx.ts 编译 xx.js
    node xx.js

    ts-node 可以直接运行 .ts 文件

    npm install ts-node -g
    ts-node xx.ts

    基础类型

    Boolean

    let isDone: boolean = false;
    
    • 1

    Number

    let decLiteral: number = 6;
    
    let bigLiteral: bigint = 100n;
    
    • 1
    • 2
    • 3

    String

    let name: string = "bob";
    
    • 1

    Array

    第一种,可以在元素类型后面接上[],表示由此类型元素组成的一个数组
    let list: number[] = [1, 2, 3];
    
    • 1

    也可以写复杂的数组类型

    interface List {
      name: string;
    }
    const list: List[] = [{ name: "xr" }];
    
    // 联合类型的数组
    const list: (string | number)[] = [1, "2"];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    第二种方式是使用数组泛型,Array<元素类型>
    let list: Array<number> = [1, 2, 3];
    
    • 1

    Tuple

    元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。

    let x: [string, number] = ["xr", 18];
    
    • 1

    Enum

    enum 类型是对 JavaScript 标准数据类型的一个补充。

    enum Days {
        Sun=3,
        Mon,
        Tue,
        Wed
    }
    console.log(Days.Sun); // 默认为 0 如果写值 则从 值上面3开始
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    反向映射

    console.log(Days[4]); // Mon
    
    • 1
    • const 枚举
    const enum Enum {
        A
    }
    
    • 1
    • 2
    • 3
    • 外部枚举

      外部枚举用来描述已经存在的枚举类型的形状。

    declare enum Enum {
        A
    }
    
    • 1
    • 2
    • 3

    Unknown

    尽量使用 Unknown 替代 any

    let notSure: unknown = 4;
    notSure = "maybe a string instead";
    
    • 1
    • 2

    Any

    let notSure: any = 4;
    notSure = "maybe a string instead";
    
    • 1
    • 2

    Void

    通常用在函数没有返回值情况

    function warnUser(): void {
      console.log("This is my warning message");
    }
    
    • 1
    • 2
    • 3

    Null 和 Undefined

    let u: undefined = undefined;
    let n: null = null;
    
    • 1
    • 2

    Never

    never 类型表示的是那些永不存在的值的类型。

    // 返回never的函数必须存在无法达到的终点
    function error(message: string): never {
      throw new Error(message);
    }
    
    // 推断的返回值类型为never
    function fail() {
      return error("Something failed");
    }
    
    // 返回never的函数必须存在无法达到的终点
    function infiniteLoop(): never {
      while (true) {}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Object

    object 表示非原始类型,也就是除 number,string,boolean,bigint,symbol,null 或 undefined 之外的类型。

    declare function create(o: object | null): void;
    
    create({ prop: 0 }); // OK
    create(null); // OK
    
    create(42); // Error
    create("string"); // Error
    create(false); // Error
    create(undefined); // Error
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    类型断言

    • “尖括号”语法 jsx 语法不支持
    let someValue: any = "this is a string";
    let strLength: number = (<string>someValue).length;
    
    • 1
    • 2
    • as 语法
    let someValue: any = "this is a string";
    let strLength: number = (someValue as string).length;
    
    • 1
    • 2

    接口 interface

    interface LabeledValue {
      label: string;
    }
    
    function printLabel(labeledObj: LabeledValue) {
      console.log(labeledObj.label);
    }
    
    let myObj = { label: "Size 101 Object" };
    printLabel(myObj);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    可选属性 ?

    有些是只在某些条件下存在,或者根本不存在

    interface LabeledValue {
      label: string;
      value?: string;
    }
    function printLabel(labeledObj: LabeledValue) {}
    let myObj = { label: "Size 101 Object" };
    let myObj2 = { label: "Size 101 Object", value: "value" };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    只读属性 readonly

    interface LabeledValue {
      readonly label: string;
    }
    
    function printLabel(labeledObj: LabeledValue) {
        // 无法分配到 "label" ,因为它是只读属性。ts(2540)
      labeledObj.label = "new label";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    额外的属性检查 [propName: string]: any;

    在接口中定义了某个属性 使用时超过这些属性直接写字面量方式会报错,写在变量中正常

    interface LabeledValue {
      label: string;
    }
    
    function printLabel(labeledObj: LabeledValue) {}
    
    // 这种写法可以
    let myObj = { label: "Size 101 Object" };
    printLabel(myObj);
    
    // 这种写法报错
    // 类型“{ label: string; value: string; }”的参数不能赋给类型“LabeledValue”的参数。对象文字可以只指定已知属性,并且“value”不在类型“LabeledValue”中。ts(2345)
    printLabel({ label: "Size 101 Object", value: "value " });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    接口改写

    propName 可以任意变量
    [propName: string] 表示以后添加的属性是 string 类型,属性值是 any 类型

    interface LabeledValue {
      label: string;
      [propName: string]: any;
    }
    
    • 1
    • 2
    • 3
    • 4

    与函数一起使用

    interface Func {
      (name: string, age: number): number;
    }
    var func: Func = function (name: string, age: number): number {
      return age;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在类中使用

    interface ClockInterface {
      currentTime: Date;
      setTime(d: Date): void;
    }
    
    class Clock implements ClockInterface {
      currentTime: Date = new Date();
      setTime(d: Date) {
        this.currentTime = d;
      }
      constructor(h: number, m: number) {}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    混合类型

    interface Counter {
      (start: number): string;
      interval: number;
      reset(): void;
    }
    
    function getCounter(): Counter {
      let counter = function(start: number) {} as Counter;
      counter.interval = 123;
      counter.reset = function() {};
      return counter;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    接口继承

    interface St extends Per {}
    
    • 1

    继承多个写法

    interface St extends Per, Stu {}
    
    • 1

    接口合并

    interface Per {
      name: string;
    }
    
    interface Per {
      age: number;
    }
    const per: Per = { name: "xr", age: 0 };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    type 类型别名

    type strType = string | number | boolean;
    let strT: strType = 10;
    strT = "11";
    
    • 1
    • 2
    • 3

    描述一个对象

    type user = {
      name: string,
    };
    
    • 1
    • 2
    • 3

    描述一个函数

    type setuser = (name: string) => void;
    
    • 1

    限制字符串的选择

    type strType3 = "男" | "女";
    function getSex(sex: strType3) {
      return sex;
    }
    getSex("男");
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在接口使用

    interface Type {
      name: string;
    }
    interface Type2 {
      age: number;
    }
    type strType2 = Type | Type2;
    // let strT2: strType2 = { name: 'zs', age: 33 }
    let strT2: strType2 = { name: "zs" };
    // let strT2: strType2 = { age: 33 };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    实现继承

    type User = {
      name: string,
    };
    
    type Per = User & {
      age: number,
    };
    
    const per: Per = { name: "xr", age: 20 };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    联合类型、 类型保护、 交叉类型

    联合类型

    let type: string | number = 1;
    type = "1";
    
    • 1
    • 2
    interface Bird {
      fly();
      layEggs();
    }
    
    interface Fish {
      swim();
      layEggs();
    }
    
    declare function getSmallPet(): Fish | Bird;
    
    let pet = getSmallPet();
    pet.layEggs();
    // 类型“Fish | Bird”上不存在属性“swim”。类型“Bird”上不存在属性“swim”。
    pet.swim();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    类型保护

    • 类型断言
    (pet as Fish).swim();
    
    • 1
    • 使用类型判定
      pet is Fish 就是类型谓词。 谓词为 parameterName is Type 这种形式,parameterName 必须是来自于当前函数签名里的一个参数名
    function isFish(pet: Fish | Bird): pet is Fish {
      return (pet as Fish).swim !== undefined;
    }
    
    if (isFish(pet)) {
      pet.swim();
    }
    
    else {
      pet.fly();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 使用 in 操作符
      对于 n in x 表达式,其中 n 是字符串字面量或字符串字面量类型且 x 是个联合类型
    function move(pet: Fish | Bird) {
      if ("swim" in pet) {
        return pet.swim();
      }
      return pet.fly();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • typeof 类型守卫
    function padLeft(value: string, padding: string | number) {
      if (typeof padding === "number") {
        return Array(padding + 1).join(" ") + value;
      }
      if (typeof padding === "string") {
        return padding + value;
      }
      throw new Error(`Expected string or number, got '${padding}'.`);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • instanceof 类型守卫

    交叉类型

    interface ErrorHandling {
      success: boolean;
      error?: { message: string };
    }
    
    interface ArtworksData {
      artworks: { title: string }[];
    }
    
    interface ArtistsData {
      artists: { name: string }[];
    }
    
    // 这些接口被组合后拥有一致的错误处理,和它们自己的数据
    
    type ArtworksResponse = ArtworksData & ErrorHandling;
    type ArtistsResponse = ArtistsData & ErrorHandling;
    
    const handleArtistsResponse = (response: ArtistsResponse) => {
      if (response.error) {
        console.error(response.error.message);
        return;
      }
    
      console.log(response.artists);
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    函数类型

    为函数定义类型

    function add(x: number, y: number): number {
      return x + y;
    }
    
    let myAdd = function (x: number, y: number): number {
      return x + y;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    书写完整函数类型

    let myAdd: (x: number, y: number) => number = function (
      x: number,
      y: number
    ): number {
      return x + y;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    可选参数和默认参数

    function buildName(firstName: string, lastName?: string) {
      if (lastName) return firstName + " " + lastName;
      else return firstName;
    }
    
    • 1
    • 2
    • 3
    • 4
    function buildName(firstName: string, lastName = "Smith") {
      return firstName + " " + lastName;
    }
    
    • 1
    • 2
    • 3

    剩余参数

    function buildName(firstName: string, ...restOfName: string[]) {
      return firstName + " " + restOfName.join(" ");
    }
    
    let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
    
    • 1
    • 2
    • 3
    • 4
    • 5

    基本用法

    class Demo {
      title = "默认值";
      constructor() {}
      say() {
        console.log(this.title);
      }
    }
    
    const demo = new Demo();
    console.log(demo.title);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    继承

    class Demo {
      constructor(public title: string) {}
    }
    
    class De extends Demo {}
    
    const demo = new De("自定义");
    console.log(demo.title);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    公共,私有与受保护的修饰符

    public 默认值在类内,类外都可以访问
    private 只能在类内部访问
    protected 可以在类内部访问,也可以在继承中访问

    class Demo {
      public title = "默认值";
      constructor(title: string) {
        this.title = title;
      }
    }
    
    const demo = new Demo("自定义");
    console.log(demo.title);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    属性的简写

    class Demo {
      constructor(public title: string) {}
    }
    
    const demo = new Demo("自定义");
    console.log(demo.title);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    class Demo {
      constructor(
        public title: string,
        private age: number,
        protected sex: string
      ) {}
    }
    
    const demo = new Demo("自定义", 20, "男");
    console.log(demo.title);
    
    属性“age”为私有属性,只能在类“Demo”中访问。
    console.log(demo.age);
    
    属性“sex”受保护,只能在类“Demo”及其子类中访问。
    console.log(demo.sex);
    
    
    class De extends Demo {
      print() {
        // 属性“age”为私有属性,只能在类“Demo”中访问。
        console.log(this.age)
        console.log(this.sex,  this.title);
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    readonly 修饰符,只读

    你可以使用 readonly 关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化。

    class Demo {
      public readonly title = "默认值";
    }
    
    const demo = new Demo();
    console.log(demo.title);
    // 无法分配到 "title" ,因为它是只读属性。ts(2540)
    demo.title = "出错了";
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    存取器 getters/setters

    class Person {
      constructor(private _name: string) {}
    
      get name() {
        return this._name;
      }
    
      set name(val: string) {
        this._name = val;
      }
    }
    const per = new Person("xr");
    console.log(per.name); // xr
    per.name = "zs";
    console.log(per.name); // zs
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    静态属性、方法

    静态属性、方法只能类调用
    静态方法中 this 指向类本身

    class Demo {
      static type = 1;
      static say() {
        return this.type;
      }
    }
    console.log(Demo.type);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    实现单例模式

    class Person {
      // 存取实例对象
      private static instance: Person;
      // 使外部 不可以 `new Person`
      private constructor() {}
      // 添加类方法返回实例对象
      static getInstance() {
        // 静态方法中 `this` 指向类本身
        if (!this.instance) {
          this.instance = new Person();
        }
        return this.instance;
      }
    }
    const per = Person.getInstance();
    const per2 = Person.getInstance();
    console.log(per === per2); // true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    抽象类 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; // 允许创建一个对抽象类型的引用
    department = new Department(); // 错误: 不能创建一个抽象类的实例
    department = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值
    department.printName();
    department.printMeeting();
    department.generateReports(); // 错误: 方法在声明的抽象类中不存在
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    泛型

    函数定义

    function identity<T>(arg: T): T {
      return arg;
    }
    
    • 1
    • 2
    • 3

    使用
    第一种是,传入所有的参数,包含类型参数

    let output = identity < string > "myString"; // type of output will be 'string'
    
    • 1

    第二种方法更普遍。利用了类型推论

    let output = identity("myString"); // type of output will be 'string'
    
    • 1

    interface 定义

    interface Identity {
      <T>(arg: T): T;
    }
    
    function identity<T>(arg: T): T {
      return arg;
    }
    
    let myIdentity: Identity = identity;
    let myIdentity2: <T>(arg: T) => T = identity;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    interface Identity<T> {
      (arg: T): T;
    }
    
    function identity<T>(arg: T): T {
      return arg;
    }
    
    let myIdentity: Identity<string> = identity;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    类中定义

    class GenericNumber<T> {
        zeroValue: T;
        add: (x: T, y: T) => T;
    }
    
    let myGenericNumber = new GenericNumber<number>();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    keyof 使用

    interface Person {
      name: string;
      age: number;
      gender: string;
    }
    
    class Teacher {
      constructor(public info: Person) {}
      getInfo<T extends keyof Person>(key: T): Person[T] {
        return this.info[key];
      }
    }
    
    const teacher = new Teacher({
      name: "xr",
      age: 20,
      gender: "男",
    });
    console.log(teacher.getInfo("gender"));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    命名空间

    同一文件下

    Demo.ts

    namespace Demo {
      export interface IDemo {
        name: string;
      }
    }
    
    const demo: Demo.IDemo = {
      name: "demo",
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Demo 是全局变量可以直接使用
    要使用 Demo 下的 IDemo 接口就必须导出

    其他文件使用

    Demo.ts

    export namespace Demo {
        export interface IDemo{
            name: string;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    xx.vue

    import { Demo } from "./ts/demo";
    const person: Demo.IDemo = { name: "xr" };
    
    • 1
    • 2

    不必要的命名空间
    再次重申,不应该对模块使用命名空间,使用命名空间是为了提供逻辑分组和避免命名冲突。

    • 上面代码改进

    demo.ts

    export interface IDemo {
      name: string;
    }
    
    • 1
    • 2
    • 3

    xx.vue

    import { IDemo } from "./ts/demo";
    const person: IDemo = { name: "xr" };
    
    • 1
    • 2

    声明文件

    外部模块

    xx.d.ts

    declare module "url" {
      export interface Url {
        protocol?: string;
        hostname?: string;
        pathname?: string;
      }
      export function parse(urlStr: string, parseQueryString?, slashesDenoteHost?): Url;
    }
    
    declare module "path" {
      export function normalize(p: string): string;
      export function join(...paths: any[]): string;
      export let sep: string;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    /// 
    import * as URL from "url";
    let myUrl = URL.parse("http://www.typescriptlang.org");
    
    • 1
    • 2
    • 3
    • 外部模块简写
      假如你不想在使用一个新模块之前花时间去编写声明,你可以采用声明的简写形式以便能够快速使用它
      xx.d.ts
    declare module "hot-new-module";
    
    • 1

    简写模块里所有导出的类型将是 any。

    import x, { y } from "hot-new-module";
    x(y);
    
    • 1
    • 2
  • 相关阅读:
    探索直播美颜SDK的未来发展方向:虚拟现实、增强现实与混合
    鸿蒙开发(四)-低代码开发
    基于Leaflet的leaflet-sidebar侧边栏组件集成
    云原生之深入解析分布式存储系统Ceph的环境部署和实战操作
    雪花算法简介
    【7.28】代码源 - 【Fence Painting】【合适数对(数据加强版)】
    dmesg和addr2line命令定位段错误
    React 组件进阶
    JavaScript 67 JavaScript HTML DOM 67.5 JavaScript HTML DOM - 改变 HTML
    JAVA学习第十课:java事件处理
  • 原文地址:https://blog.csdn.net/weixin_43512977/article/details/127978861