TypeScript

发布于:2025-08-02 ⋅ 阅读:(17) ⋅ 点赞:(0)

TypeScript安装

TypeScript 的命令行工具安装方法如下:npm install -g typescript

以上命令会在全局环境下安装 tsc 命令,安装完成之后,我们就可以在任何地方执行 tsc 命令了

直接运行ts代码,需要手动安装插件:

//全局安装ts-node

npm i -g ts-node

//在项目目录下,生成tsconfig.json

tsc --init 

npm安装package.json中的依赖 npm i

package.json文件内容 

{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "1.js",
  "directories": {
    "test": "test"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/node": "^20.10.4",
    "ts-node": "^10.9.2",
    "tslib": "^2.6.2",
    "typescript": "^5.2.2"
  }
}

各类型定义

简单类型

let flag: boolean = false;
  let num: number = 15;
  let str: string = "abc";
  let u: undefined = undefined;
  let n: null = null;


  //声明的变量有多种类型--联合类型声明
  let id: number | string = 10;

  //任意类型
  let x: any = true;
  x = 111;
  x = "222";

引用类型

  //数组定义
  let arr = [1, 2, 3, "4"];
  let arr1: number[] = [1, 2, 3];
  let arr2: string[] = ["A", "B"];
  let arr3: (number | string)[] = [1, 2, 3, "4"];//联合类型声明
  let arr4: any[] = [1, 2, 3, "4"];

  //数组泛型
  let arr5: Array<number> = [1, 2, 3];
  let arr6: Array<number | string> = [1, 2, 3, "4"];

接口

接口(Interfaces)可以用于对「对象的形状(Shape)」进行描述。声明对象的模版

  //对象定义
  //定义接口,首字母大写
  interface Person {}
  class Person {}
  //开发中使用IPerson:区分class
  interface IPerson {
    //变量
    id: number;
    name: string;
    age?: number;//可选属性
    [propName: string]: any; //任意属性,需要注意的是,一旦定义了任意属性,那么确定属性和可选属性都必须是它的子属性
  }
  //id和name受到IPerson的约束
  let obj: IPerson = {
    id: 1,
    name: "jack",
  };
  let Item1: IPerson[] = [
    { id: 1, name: "jack" },
    { id: 1, name: "jack" },
  ];
  let Item2: Array<IPerson> = [
    { id: 1, name: "jack" },
    { id: 1, name: "jack" },
  ];

接口中定义方法:

 //接口中定义方法
  interface IPerson2 {
    name: string;
    age: number;
    say(); //定义方法
    action(v: number): number; //定义方法
  }

  let o: IPerson2 = {
    name: "jack",
    age: 20,
    say() {},
    action(v) {
      return this.age;
    },
  };

  //接口修饰(约束)方法
  interface ISum {
    (n1: number, n2: number): number;
  }
  let sum: ISum = (n1, n2) => n1 + n2;

多层级结构:

  interface IResult {
    id: number;
    value: number;
  }
  interface ITest {
    code: number;
    msg?: string;
    result: IResult[];
  }

  let o2: ITest = {
    code: 2000,
    msg: "success",
    result: [
      {
        id: 1,
        value: 100,
      },
    ],
  };

接口的继承

  interface IPerson3 {
    id: Number;
    name: string;
    age?: number;
    say();
  }

  interface IAction extends IPerson3 {
    action(v: number, v2: number): number;
  }

  let o3: IAction = {
    name: "jack",
    id: 20,
    say() {},
    action(v) {
      return this.age;
    },
  };

函数类型

一个函数有输入和输出,要在 TypeScript 中对其进行约束,需要把输入和输出都考虑到

  //函数类型定义--函数有输入和输出类型
  function sum1(x: number, y: number): number {
    return x + y;
  }

  //输出无返回值
  function sum2(x: number, y: number): void {
    console.log(x + y);
  }

  //输入参数定义默认值
  function sum3(x: number = 1, y: number = 2): number {
    return x + y;
  }

  //输入参数选填参数.?选填
  function sum4(x: number = 1, y?: number): number {
    return x + (y || 4);
  }

  const fn5 = function ({ id, name }: { id: number; name: string }): {
    pid: number;
    title: string;
  } {
    return { pid: id, title: name };
  };

  const f6 = ({
    id,
    name,
  }: {
    id: number;
    name: string;
  }): { pid: number; title: string } => {
    return { pid: id, title: name };
  };

泛型

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定 类型的一种特性。泛型变量T , T表示任何类型

什么时候需要定义泛型函数?要创建一个可重用的组件,其中的数据类型就必须要兼容很多的类型

  function fn1(a: number, b: number): number[] {
    return [a, b];
  }
  function fn2(a: string, b: string): string[] {
    return [a, b];
  }
  //fn1和fn2很类似,使用泛型定义方法
  function fn<T>(a: T, b: T): Array<T> {
    return [a, b];
  }
  fn(10, 20);
  fn("10", "20");

泛型约束

function f4(arg: T): T {    

        console.log(arg.length); // 错误: T不存在length属性 比如数值等

}

使用了 extends 约束了泛型 T 必须符合接口 LengthN 的形状,也就是必须包含 length 属性

  interface ILength {
    length: number;
  }
  function fn4<T extends ILength>(str: T): number {
    return str.length;
  }
  let o5: ILength = {
    length: 6,
  };
  fn4(o5);
  fn4<Array<number>>([1, 2.3]); //Array<number>也是有length属性的
  fn4<{ id: number; length: number }>({ id: 1, length: 10 }); //{ id: number; length: number }包含length属性的接口约束


  interface INamed {
    name: string;
    [propName: string]: any;
  }
  //要求传入的参数必须有name属性
  function f5<T extends INamed>(x: T): string {
    return x.name;
  }
  f5({ name: "jack", age: 18 });
  f5<INamed>({ name: "jack", age: 18 });

  /*************************多类型泛型****************************** */
  interface IMultiply<T, U> {
    first: T;
    second: U;
  }
  const o6: IMultiply<Number, string> = {
    first: 1,
    second: "1",
  };
  /*****************泛型在函数中的应用******************** */
  //函数声明
  function f6<T>(n1: T, n2: T): T[] {
    return [n1, n2];
  }
  //函数表达式
  let f7 = function <U>(n1: U, n2: U): Array<U> {
    return [n1, n2];
  };
  //泛型&箭头函数
  let f8 = <U>(n1: U, n2: U): U[] => {
    return [n1, n2];
  };

  /*************************多类型泛型****************************** */
  interface IMultiply<T, U> {
    first: T;
    second: U;
  }
  const o6: IMultiply<Number, string> = {
    first: 1,
    second: "2",
  };

  /**
   * 扩展:定义一个函数,传入长度和值,返回数组(数组的长度是传入的长度,数组的值是传入的参数)
   * **/
  let createArr = function <T>(len: number, v: T): T[] {
    let arr: T[] = [];
    for (let i = 0; i < len; i++) {
      arr[i] = v;
    }
    return arr;
  };
  
  interface ICreateArr {
    <T>(len: number, v: T): T[];
  }
  let createArr1: ICreateArr = <T>(len, v) => {
    let arr: T[] = [];
    for (let i = 0; i < len; i++) {
      arr[i] = v;
    }
    return arr;
  };

  class Cat {
    name: string;//必须要声明
    color: string;//必须要声明
    constructor(name, color) {
      this.name = name;
      this.color = color;
    }
    eat(v: string) {
      return v;
    }
  }
  let cat = new Cat("jack", "black");

  //类也可以受到接口的约束
  interface IFeatures {
    name: string;
    age?: number;
    action(): string;
  }
  //接口中的属性和方法,类中必须要实现
  class Person implements IFeatures {
    name: string;
    age: number;
    //构造器用到的参数,要在类中提前声明
    constructor(name, age) {
      this.name = name;
      this.age = age;
    }
    action(): string {
      return this.name;
    }
  }

类单继承多实现

  //类也可以受到接口的约束
  interface IFeatures {
    name: string;
    age?: number;
    action(): string;
  }
  //接口中的属性和方法,类中必须要实现
  class Person implements IFeatures {
    name: string;
    age: number;
    //构造器用到的参数,要在类中提前声明
    constructor(name, age) {
      this.name = name;
      this.age = age;
    }
    action(): string {
      return this.name;
    }
  }

  //类继承&实现
  interface IWarning {
    sing(ball: string): string;
  }
  interface ILight {
    lightOn();
    lightOff(): boolean;
  }
  class Door {
    type: string;
    constructor(type) {
      this.type = type;
    }
  }
  class SecurityDoor extends Door implements IWarning {
    constructor(type) {
      super(type);
    }
    sing(ball: string): string {
      return "";
    }
  }

  class Car implements IWarning, ILight {
    height: number;
    color: string;
    constructor(height, color) {
      this.height = height;
      this.color = color;
    }
    lightOn() {}
    lightOff(): boolean {
      return true;
    }
    sing(ball: string): string {
      return "";
    }
  }

修饰符

public&private&protected

public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的

private 修饰的属性或方法是私有的,不能在声明它的类的外部访问,子类也不能进行访问

protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的

  /*****************private修饰的属性或方法是私有的,不能在声明它的类的外部访问*************** */
  class Cat2 {
    private name: string;
    private color: string;
    constructor(name: string, color: string) {
      this.name = name;
      this.color = color;
    };
    private say():string{
      return "";
    }
  }

  let cat2 = new Cat2("jack", "black");
  cat2.name; //属性“name”为私有属性,只能在类“Cat2”中访问。ts(2341)
  cat2.say();//属性“say”为私有属性,只能在类“Cat2”中访问。ts(2341)
  
  //private修饰的属性和方法在子类中也是访问不到的
  class Test extends Cat2 {
    constructor(name: string, color: string) {
      super(name, color);
    }
  }
  let test = new Test("jack", "red");
  test.name;//属性“name”为私有属性,只能在类“Cat2”中访问。ts(2341)

通过公共方法获取私有属性:

  class Employee {
    protected salary: number;
    public name: string;
    constructor(salary: number, name: string) {
      this.name = name;
      this.salary = salary;
    }
    protected say(): string {
      return "";
    }
    public getSalary(): number {
      return this.salary;
    }
  }
  let emploee = new Employee(1000, "jack");
  let s: number = emploee.getSalary();
  console.log(s);//1000

静态修饰符static

属性或者方法不需要实例化

  class Employee2 {
    static salary: number = 1000;
    public name: string;
    constructor(name: string) {
      this.name = name;
    }
    protected say(): string {
      return "";
    }
    public getSalary(): number {
      return Employee2.salary;
    }
  }
  console.log(Employee2.salary);

只读readonly

  /****************只读修饰符:属性初始化后不能被修改*********************** */
  class Employee3 {
    readonly salary: number = 1000;
    public name: string;
    constructor(name: string,salary:number) {
      this.name = name;
      this.salary = salary;//readonly修饰的属性只能在构造函数中进行修改
    }
    public setSlary(s: number) {
      this.salary = s; //无法为“salary”赋值,因为它是只读属性。ts(2540)
    }
  }

类型断言

  //类型断言
  let n1: any = 100;
  let n2 = n1;
  console.log(typeof n2); //number.类型有any变成number

  //ts中提供了二种类型断言的语法
  //1、<>语法
  let n3: any = 100;
  let n4 = <number>n3; //告诉编译器n4的类型是number
  //2、关键字as断言
  let n5 = n3 as number; //告诉编译器n4的类型是number

断言的使用

  //fn函数在调用的时候,传入的参数可能是数字也可能是字符串
  function fn(v: string | number): void {
    if (typeof v === "number") {
      let v1: number = v as number;
      console.log(v1 ** 2); //平方
    } else {
      console.log((v as string).toLowerCase());
    }
  }
  fn(5);

枚举

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

  //枚举定义:enum 枚举名称 {成员1,成员2,成员3}
  enum color {
    red,
    green,
    blue,
  }
  //默认情况下,从0开始为元素编号。 你也可以手动的指定成员的数值
  console.log(color.red); //0,获取到的是下标
  //通过成员0转换成枚举值
  console.log(color[0]); //red,通过下标获取到的是枚举值,类型是字符串

  let c1: color = color.red;
  let c2: color = color[0]; //不能将类型“string”分配给类型“color”。ts(2322)
  let c3: string = color[0]; //字符串类型

  //能不能修改枚举类型值
  color.green = 5; //无法为“green”赋值,因为它是只读属性。ts(2540)

  //具体使用场景:使用枚举,可以限定使用的数据
  enum Day {
    Sunday,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Frisday,
    Saturday,
  }
  function fn(): Day {
    let n = new Date().getDay();
    console.log(Day[n]);
    return n;
  }
  //也可以手动的指定成员的数值
  enum Color2 {
    Red = 1,
    Green,
    Blue,
  }
  let c4: Color2 = Color2.Green;
  console.log(c4);

  //枚举可以是小数
  enum Color5 {
    Red = 1.6,
    Green,
    Blue,
  }
  let c5 = Color5.Green;
  console.log(c5); //2.6 步长值+1

元组

数组合并了相同类型的对象,而元组(Tuple)合并了不同类型的对象

  var lists: number[] = [1, 2, 3];
  //数组泛型 不允许有其它的类型
  var lists2: Array<string> = ["a", "b", "c"];
  var lists3: Array<string | number> = ["a", "b", 1, 2];
  //任意值
  var lists4: any[] = ["a", 1, true];

  //元组的声明:使用[]来定义元组类型
  let tuple: [number, string] = [1, "jack"];
  console.log(typeof tuple); //object,
  let tuple2: [number, number[]] = [1, [2, 3, 4]];

  interface IPerson {
    id: number;
    name: string;
  }
  /*************通过定义方式来区别是元组还是数组************************* */
  let tuple3: [IPerson] = [{ id: 1, name: "jack" }]; //元组
  let tuple4: IPerson[] = [{ id: 1, name: "jack" }]; //数组定义
  let tuple5: [IPerson, Boolean, number[]] = [
    { id: 1, name: "jack" },
    true,
    [1, 2, 3],
  ];

  //返回元组
  function fn(x: number, y: string): [number, string] {
    return [x, y];
  }
  let tuple6 = fn(1, "2");
  console.log(tuple6[0]);

类型别名

  //type 类型别名,为类型起的新名字
  type abc = string;
  let s: abc = "hello"; //===let s:string = 'hello'

  //可以简写一些类型
  type xyz = string | number | boolean;
  let n1: string | number | boolean = "1";
  let n2: xyz = "2"; //使用的时候更简单

  //type和interface的区别?
  //interface同一个类型,属性会合并,type不行
  interface IPerson {
    id: number;
  }
  interface IPerson {
    name: string;
  }
  let p: IPerson = {
    id: 1,
    name: "jack",
  };

网站公告

今日签到

点亮在社区的每一天
去签到