typescript基础用法

2,130 阅读19分钟

一.学习ts的目的

作为一种由 Microsoft 开发的开源语言,TypeScript 近年来一直在我们最喜爱的语言列表
中名列前茅。正如您从名称中猜到的那样,TypeScriptJavaScript 的超集,它为 
JavaScript 的功能引入了可选类型(以及其他功能),通过降低出现错误的机会提高了可靠
性。更好的是:Angular 2 本身实际上是用 TypeScript 编写的。虽然有一些技术可以直接
运行 TypeScript——DenoAngular——但它主要被转换为 JavaScript,可以在任何 Web 应
用程序中使用。 
  • TypeScript 是JavaScript的严格超集。这意味着任何和所有有效的 Javascript 代码都可以像 TypeScript 一样完美地运行。事实上,“编译”打字稿实际上transpiles代码回香草的JavaScript。因此,它与任何现代浏览器和任何平台兼容——JavaScript 几乎可以在任何地方运行——但它在编译阶段提供额外的检查,以提高与 JavaScript 相比的可靠性。
  • 与松散类型的JavaScript 不同,TypeScript 是强类型的:必须声明每个变量将包含什么样的数据。虽然这可能会稍微增加非常小的简单程序的开发时间,但许多现代软件包含数千行代码,跨多个文件,通常由不同的作者编写。在这种情况下,明确定义哪些类型的变量是可以接受的可以防止难以定位的错误成为现实。
  • 除此之外,TypeScript 真的只是 JavaScript,具有JavaScript的所有优点(和一些缺点)。

二.ts的基本用法

1.ts的类型

1.1 ts环境搭建

1. 打开命令行,键入npm i -g typescript 全局安装TS
2. 继续在命令行环境下键入 tsc -init 进行初始化,
你会发现根目录下多了 tsconfig.json 的文件,记录了编译成JS的选项
3. 创建ts文件
4. 打开VSCode进入该目录,按下 Ctrl+shift+B 快捷键会进行编译,初次编译会选择编译模式
5. 输入node命令运行js代码
npm install -g ts-node 
npm install -D tslib @types/node

1.1.1在浏览器中运行ts

  • 建立好文件夹后,打开 VSCode,把文件夹拉到编辑器当中,然后打开终端,运行npm init -y,创建package.json文件。
  • 生成文件后,我们接着在终端中运行tsc -init,生成tsconfig.json文件。
  • 新建src和build文件夹,再建一个index.html文件。
  • 在src目录下,新建一个page.ts文件,这就是我们要编写的ts文件了。
  • 配置tsconfig.json文件,设置outDir和rootDir(在 15 行左右),也就是设置需要编译的文件目录,和编译好的文件目录。
  • 然后编写index.html,引入,当让我们现在还没有page.js文件。
  • 编写page.ts文件,加入一句输出console.log('jspang.com'),再在控制台输入tsc,就会生成page.js文件
  • 再到浏览器中查看index.html文件,如果按F12可以看到jspang.com,说明我们的搭建正常了。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src='./build/page.js'></script>
    <title>Document</title>
</head>
<body>
    
</body>
</html>

1.2基本类型申明

作为js的超集,ts支持js的所有数据类型,包含

  • boolean 、number、string、null、 undefined、 Symbol
  • undefined 和null 类型的数据只能被赋值undefined 和null, 但是这个类型是所有类型的子类型
  • void 空类型
  • any和类型推断 1.undefined和null是所有类型子类型,都可以赋值
let num: Symbol = undefined;
let num: number = undefined;
// undefined类型, 只能给undefined
let u: undefined = undefined;
let n: null = null;

2.在ts中,变量在声明的时候,如果没有定义其类型,会被识成默认类型

let str; 
str = 'I am wangsu';
str = 1024; 
// 未定义类型,直接赋值 let num= 124; 
// 等同于 let num:number = 124, 
//在后面代码如果赋予num一个string会被报错

3.void类型的用法

//void类型像是与any类型相反,它表示没有任何类型。 当一个函数没有返回值时,你通常会见到其返回值类型是 void: 
function warnUser(): void { 
alert("This is my warning message"); 
} 
//声明一个void类型的变量没有什么大用,因为你只能为它赋予undefined: 
let a: void = undefined;

4.any类型的用法

有时候,我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。 这些值可能来自于
动态的内容,比如来自用户输入或第三方代码库。 这种情况下,我们不希望类型检查器对这些
值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用 any类型来标记这些变量:

//这里的any表示任意类型,因此下面修改不会造成任何报错
let ws:any=12
ws="i don't kown my type"
ws="wo shi wagsu"
console.log(ws);

5.unknown类型的用法

有时,我们会遇到类型事先未知的情况,即可以是任何类型。在 TS v3 之前,我们使用any可以定义任何类型。但是这让ts失去了它的价值,比如失去 ts提供的任何类型安全。

//使用any
const x: any = {
  a: "ws",
  b: "qy"
};
//可以访问该对象的属性,即x.a与x.b不会有什么问题。
//问题是如果你试图访问x.c值,Typescript 不会抛出错误,因为对象x可以是任何东西。

如你所见,这可能是许多错误的来源,因为 Typescript 在构建期间捕获的常见错误将被允许通过。这是因为当你使用any类型时,会退出类型检查。因此将以上代码修改为

const x: unknown = {
  a: "wx",
  b: "qy"
};
console.log((x as {a: string; b: string; }).b)

6.never类型的用法

let x: never;
let y: number;
// 运行错误,数字类型不能转为 never 类型
x = 123;

// 运行正确,never 类型可以赋值给 never类型
x = (()=>{ throw new Error('exception')})();

// 运行正确,never 类型可以赋值给 数字类型
y = (()=>{ throw new Error('exception')})();

// 返回值为 never 的函数可以是抛出异常的情况
function error(message: string): never {
    throw new Error(message);
}
// 返回值为 never 的函数可以是无法被执行到的终止点的情况
const ws=function(): never {
    while (true) {}
    }

7.类型推导

当我们很清楚当前就是Number类型,就可以通过类型推导的方式来调用number类型

//如果object是小写则无法调用对象上的一些方法,需要将它的类型做一个类型推导
let j:object={} 
//这里如果是大写的Object,那么可以直接调用它的原型上的方法,例如toString() 
let j:Object={} //j类型是number 基本数据类型 
j=new String("123") //j的类型是Number 基本数据的包装类型
j=new Number(123) //类型推导,将j转化为number类型,这是j就是0一个number类型对象,因此可以调用它的toString方法
let str=(<Number>j).toString() //类型推导的第二种写法
let str2=(j as Number).toString(); //这里的j对应的object是小写的 
let str=j.toString() 
console.log(str)

8.断言

有时候你会遇到这样的情况,你会比 TypeScript 更了解某个值的详细信息。通常这会发生在你清楚地知道一个实体具有比它现有类型更确切的类型。通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。类型断言好比其他语言里的类型转换,但是不进行特殊的数据检查和解构。它没有运行时的影响,只是在编译阶段起作用。

//尖括号语法
let someValue: any = "this is a string"; 
let strLength: number = (<string>someValue).length; 
//as语法
let someValue: any = "this is a string"; 
let strLength: number = (someValue as string).length;

1.3 类型守卫

1.3.1 in关键字

interface Admin {
  name: string;
  peee: string[];
}
interface Emplyee {
  name: string;
  startData: Date;
}

type UnknownEmployee = Emplyee | Admin;

function printEmplo(emp: UnknownEmployee) {
    //确定这个对象中包含某个属性
  if ("peee" in emp) {
    console.log("peee" + emp.peee);
  }
  if ("startData" in emp) {
    console.log("peee" + emp.startData);
  }
}

1.3.2typeof

typeof 类型保护只支持两种形式:typeof v === "typename" 和 typeof v !== typename,"typename" 必须是 "number", "string", "boolean" 或 "symbol"。 但是 TypeScript 并不会阻止你与其它字符串比较,语言不会把那些表达式识别为类型保护。

let ws:number
let qy:typeof ws=1234
console.log(qy);

1.3.3instanceof

interface Padder{
    //定义一个函数类型,返回值类型是一个string
    getPaddingString():string
}

//定义一个类
class SpaceReapeat implements Padder{
    constructor(private numSpaes:number){

    }
    getPaddingString(){
        return Array(this.numSpaes+1).join('')
    }

}
let padder:Padder=new SpaceReapeat(6)
if(padder instanceof SpaceReapeat){

}

1.3.4 is

function isNumber(x: any): x is number {
  return typeof x === "number";
}

function isString(x: any): x is string {
  return typeof x === "string";

1.4枚举

枚举可以用一些名字有意义的常量,更加清晰表达我们开发者的意图

1.4.1 异构枚举

enum Order{
    start='start',
    name='ws',
    age=12
}
console.log( Order);
//{ '12': 'age', start: 'start', name: 'ws', age: 12 }

1.4.2数字枚举的反向映射

enum Shop{
    first=0,
    second=1,
    end=3
}
console.log(Shop.first);//0
console.log(Shop[Shop.first]);//first

1.5 数组

数组有字符串数组,对象数组,元组,数字数组

//数组定义第一种方式
let list:number[]=[1,23,5,3,5,76,3] 
console.log(list)
//定义数组的第二种方式,使用数组泛型,Array<元素类型>:
let arr:Array<number>=[1,4,6,87]
console.log(arr)

1.5.1元组

ts的数组只能存放单一数据类型的元素,元组则可以很好的解决此问题。元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。 比如,你可以定义一对值分别为string和number类型的元组。

//这里定义时前面的中括号种数据类型与后面中括号中的数据类型要一一对应
let list1:[string,number,null]=["ws",1234,null]
console.log(list1)
1.5.1.1 元组的属性
  • 元组可以是只读的

在给只读元组类型赋值的时候,允许将常规的元组类型赋值给只读元组类型,但是不允许将只读元组类型给常规元组类型

const ws:readonly[number,number]=[0,0]//元组中数据只可读
  • 元组中的元素可以是可选的,使用?
const arr=[t1,t2,t3?,...tn?]
  • 元组中的剩余元素
const ws:[number,strig,...string[]]=[0,'s','d','f','g']

1.6函数

1.6.1函数的类型别名

type age=number;
type AgeCreater=()=>age;
function getAge(arg:AgeCreater):age{
     return arg()
}

1.6.2函数重载

函数重载是指在同一作用域内,可以有一组具有相同函数名,不同参数列表的函数,这组函数被称为重载函数。重载函数通常用来命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。简单来说就是函数名一样,函数的参数不一样

//函数重载申明可以多个,但是实现能有一个
//函数重载:函数名一样,函数的参数不一样

//函数申明
function fn(name:string,age:number):void;
function fn(name:string,age:number,gender:string):void;

//函数实现
function fn(name:string,age:number,gender?:string):void{
    if(arguments.length>2){
        console.log("函数有三个参数")
    }
    else{
        console.log("函数有两个参数");
        
    }
}

fn("王苏",20)
fn("王苏",20,"男")
//函数重载:重载是方法名字相同,而参数不同,返回类型可以相同也可以不同。

//每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。

//参数类型不同:
function disp(string):void; 
function disp(number):void;

//参数数量不同:
function disp(n1:number):void; 
function disp(x:number,y:number):void;

//参数类型顺序不同:
function disp(n1:number,s1:string):void; 
function disp(s:string,n:number):void;

1.6.3函数参数类型

1.函数参数中加?表示该参数可有可无

  //?号表示可选的参数
    function fn2(name?:string,gender?:string):number{
        return 1
    }
    console.log(fn2("王苏"))//1
    console.log(fn2("王苏","男"))//1

2.函数参数中=表示是函数的默认参数

function fn3(name:string,gender:string="男"){
        return gender
    }

    console.log(fn3("王苏"))//男

3. ...剩余参数,剩余参数一般表示函数的最后一个参数

  function fn4(name:string,...arg:string[]):number{
        console.log(arg)
        return 1;
    }
    fn4("张三","李四","孙晓","户菲")//[ '李四', '孙晓', '户菲' ]
    

4.函数无返回值

function sayHello(): void {
  console.log("hello world");
}

1.7对象

1.7.1 interface关键字

  interface s{
        a:number,
        b:string,
        c:number[]
    }
    let v:s={
        a:1,
        b:'qy',
        c:[1,2,3,4]
    }
    console.log(v);

1.7.2可选属性

interface Person {
    name: string;
    age?: number;
}

let tom: Person = {
    name: 'Tom'
};

1.7.3 任意属性

interface Person {
    name: string;
    age?: number;
    [propName: string]: any;
}

let tom: Person = {
    name: 'Tom',
    gender: 'male'
};

1.7.4只读属性

interface Person {
    readonly id: number;
    name: string;
    age?: number;
    [propName: string]: any;
}

let tom: Person = {
    id: 89757,
    name: 'Tom',
    gender: 'male'
};

tom.id = 9527;

2.ts中的calss类

2.1 基本用法

//申明类
class Person {
    //属性,成员变量
  name: string = "张三";
  age: number;

  //构造函数,创建对象会默认调用的方法
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  //定义方法,成员方法
  //成员变量,成员方法只能由当前对象调用,当前类无法直接调用
  sayHello(msg: string="默认信息"): void {
    console.log(this.name + msg);
  }
}
 let p1=new Person("王苏",20)
 p1.sayHello()

2.2.继承

2.2.1.extends

//申明类
class Person {
    //属性,成员变量
  name: string = "张三";
  age: number;

  //构造函数,创建对象会默认调用的方法
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  //定义方法,成员方法
  //成员变量,成员方法只能由当前对象调用,当前类无法直接调用
  sayHello(msg: string="默认信息"): void {
    console.log(this.name + msg);
  }
}

//student继承当前person类的方法与属性
class Student extends Person{
    
}
 let p2=new Student("王苏",23)
 p2.sayHello()

2.2.2 super

//申明类
class Person {
    //属性,成员变量
  name: string = "qy";
  age: number;

  //构造函数,创建对象会默认调用的方法
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  //定义方法,成员方法
  //成员变量,成员方法只能由当前对象调用,当前类无法直接调用
  sayHello(msg: string="默认信息"): void {
    console.log(this.name + msg);
  }
}

//student继承当前person类的方法与属性
class Student extends Person{
    //这里是学生自己的属性
    gender:string;
    constructor(name:string,age:number,gender:string){
        //调用父类的构造函数初始化name和age的信息
        //这里的super一定在第一个
        super(name,age)
        //初始化自己的gender信息
        this.gender=gender;
    }

    sayHello(msg: string="默认信息"): void {
        //利用super调用父类的方法
        super.sayHello();
         //打印当前子类的信息
        console.log("当前性别是:",this.gender)
      }
}

 let p2=new Student("王苏",23,"男")
 p2.sayHello()

2.3.成员变量

2.3.1.public

共有的成员变量,为默认状态,可以被子类继承

//申明类
class Person {
    //属性,成员变量,这里是共有成员变量
 public  name: string = "张三";
 public age: number;

  //构造函数,创建对象会默认调用的方法
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  //定义方法,成员方法
  //成员变量,成员方法只能由当前对象调用,当前类无法直接调用
  sayHello(msg: string="默认信息"): void {
    console.log(this.name + msg);
  }
}

//student继承当前person类的方法与属性
class Student extends Person{
    //这里是学生自己的属性
    gender:string;
    constructor(name:string,age:number,gender:string){
        //调用父类的构造函数初始化name和age的信息
        //这里的super一定在第一个
        super(name,age)
        //初始化自己的gender信息
        this.gender=gender;
    }

    sayHello(msg: string="默认信息"): void {
        //利用super调用父类的方法
        super.sayHello();
         //打印当前子类的信息
        console.log("当前性别是:",this.gender)
      }
}

 let p1=new Person("王苏",20)
 p1.sayHello()

 let p2=new Student("qy",23,"女")
 p2.sayHello()

2.3.2private

私有成员变量,表示父亲独有的,无法被继承,只能在当前类内部使用

//申明类
class Person {
    //属性,成员变量
 public  name: string = "张三";
 public age: number;
 private job:string="IT"
  //构造函数,创建对象会默认调用的方法
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  //定义方法,成员方法
  //成员变量,成员方法只能由当前对象调用,当前类无法直接调用
  sayHello(msg: string="默认信息"): void {
    console.log(this.name + msg);
    //仅能在当前class类中使用私有成员变量
    console.log(this.job)
  }
}

//student继承当前person类的方法与属性
class Student extends Person{
    
    //这里是学生自己的属性
    gender:string;
    constructor(name:string,age:number,gender:string){
        //调用父类的构造函数初始化name和age的信息
        //这里的super一定在第一个
        super(name,age)
        //初始化自己的gender信息
        this.gender=gender;
    }

    sayHello(msg: string="默认信息"): void {
        //利用super调用父类的方法
        super.sayHello();
         //打印当前子类的信息
        console.log("当前性别是:",this.gender)
      }
}

 let p1=new Person("王苏",20)
 p1.sayHello()

 let p2=new Student("王苏",23,"男")
 p2.sayHello()

2.3.3.protected

受保护的成员变量,只能在当前类以及它的子类中使用,在外部无法进行访问

//protected 受保护的
- 和 private 类似,但是可以被继承

class Person {
    protected name: string;
    constructor(name: string) { 
        this.name = name; 
    }
}

class Employee extends Person {
    private department: string;

    constructor(name: string, department: string) {
        super(name)
        this.department = department;
    }

    public getElevatorPitch() {
        return `Hello, my name is ${this.name} and I work in ${this.department}.`;
    }
}

let howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
console.log(howard.name); // 错误

//注意,我们不能在 Person类外使用 name,但是我们仍然可以通过
//Employee类的实例方法访问,因为Employee是由 Person派生而来的。

2.4Setter与Getter

通过 Getter 和 Setter 的形式来访问和修改private属性。

//申明类
class Person {
  //属性,成员变量
  public name: string = "秦莺";
  public age: number;
  //私有成员
  private _job: string = "IT";
  //受保护的成员变量
  protected house: string = "这是一个好房子";
  //构造函数,创建对象会默认调用的方法
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
//从外部间接访问私有成员
  set job(job: string) {
      console.log("当前set方法执行了")
    this._job = job;
  }
  get job(): string {
    return this._job;
  }
  //定义方法,成员方法
  //成员变量,成员方法只能由当前对象调用,当前类无法直接调用
  sayHello(msg: string = "默认信息"): void {
    console.log(this.name + msg);
    //仅能在当前class类中使用私有成员变量
    console.log(this._job);
  }
}

//student继承当前person类的方法与属性
class Student extends Person {
  //这里是学生自己的属性
  gender: string;
  constructor(name: string, age: number, gender: string) {
    //调用父类的构造函数初始化name和age的信息
    //这里的super一定在第一个
    super(name, age);
    //初始化自己的gender信息
    this.gender = gender;
  }

  sayHello(msg: string = "默认信息"): void {
    //利用super调用父类的方法
    super.sayHello();
    //打印当前子类的信息,因为get,所以现在可以访问私有成员变量
    console.log("当前性别是:", this.gender,this.job);
  }
}

let p1 = new Person("王苏", 20);
p1.sayHello();

let p2 = new Student("王苏", 23, "男");
p2.sayHello();

let stu=new Student("小明",21,"男")
//这里修改job相当于给set方法传递了一个参数
stu.job="teacher"
stu.sayHello()

2.5静态成员

不需要实例化访问的成员称之为静态成员,即只能被类访问的成员 static 关键字

class Person {
    //静态变量
    static country = "china";
    //京塔方法
    static sayhello() { 
        console.log("hello")
    }
    constructor () { }
}

let p1 = new Person();  
let p2 = new Person(); 

console.log(Person.country)  //静态变量,直接通过类型来访问
console.log(p1.country) //错误

2.6抽象类

通过封装一个抽象类来传递一个方法,但是这个方法的功能是各式各样的

abstract class Girl{
    abstract skill()  //因为没有具体的方法,所以我们这里不写括号

}

class Waiter extends Girl{
    skill(){
        console.log('ws,请喝水!')
    }
}

class BaseTeacher extends Girl{
    skill(){
        console.log('ws,来个泰式按摩吧!')
    }
}

class seniorTeacher extends Girl{
    skill(){
        console.log('ws,来个SPA全身按摩吧!')
    }
}

3.接口

3.1接口对类进行规范

声明一个Human的接口,里面描述了Human应该有的属性,行接口可以对类进行规范,还可以对对象进行规范

interface Human{
    name:string;
   age:number;
   gender:string;
   say():void;
}

//实现接口
class People implements Human{
    name:string="王苏";
    age:number=20;
    gender:string="男";
    say():void{
     console.log("实现接口")
    };
}
//接口可以被很多类实现
class Enginer implements Human{
    name:string="秦莺";
    age:number=20;
    gender:string="女";
    say():void{
     console.log("实现接口转换")
    };
}

3.2接口对对象进行规范

interface Shape {
    head: string;
    arm: string;
}
interface Person {
    name: string;
    age: number;
    shape: Shape;
    say(word: string): void;
}

let jack: Person = {
    name: 'Jack',
    age: 18,
    shape: {
        head: 'head',
        arm: 'arm'
    },
    say(word: string) {
        console.log(word)
    }
}
jack.say('hi')

3.3接口属性

  • 接口的只读属性

一些对象属性只能在对象刚刚创建的时候修改其值。 你可以在属性名前用 readonly来指定只读属性:

interface Person {
    readonly name: string
}

let jack: Person = {
    name: 'ws'
}

jack.name = 'qy' // error: name 是只读的
  • 接口的可选属性

接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。 可选属性在应用“option bags”模式时很常用,即给函数传入的参数对象中只有部分属性赋值了。

interface Person {
    gender: string,
    age?: number
}

let jack: Person = {
    gender: 'qy'
    // 可以不赋值 age 属性,因为是可选的
}

4.泛型

4.1泛型约束

泛型无法知道具体的类型,所以无法操作它的属性和方法

function Test<T> (a:T):void {
  console.log(a.length);  // error
}
Test<string>('ws')

当你明确知道泛型中有哪些属性方法时,可以通过 extends 进行泛型约束,写在声明函数名的后面

interface hasLengthProp {
    length : number;
}
function Test<T extends hasLengthProp>(a:T):void {
    console.log(a.length);
}

利用泛型约束泛型,使用了继承

function change<T extends U,U>(a:T,b:U):void {
    console.log(a);
}

change({a:1,b:2,c:3},{a:1,b:2})

4.2.泛型接口

在接口中定义泛型,如果接口中只定义了一个匿名函数的类型,直接赋值即可

interface Test {
  <T>(name:T):void
}
let say:Test; // 直接赋值
say = function<T>(name:T):void {
  console.log(name);
}
say('ws')

如果接口中包含多个属性,这个接口就是一个对象的描述

interface objType {
    demo<T>(name:T):void;
    age:string;
  }
  let say:objType; // 对象的描述
  say.demo = function<T>(name:T):void {
    console.log(name);
  }
  say.demo<string>('ws')

4.3.泛型类

就是在泛型里面使用类型变量 类那节说过,类有两部分:静态部分和实例部分。 泛型类指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型

class SelectGirl<T> {
  constructor(private girls: T[]) {}
  getGirl(index: number): T {
    return this.girls[index];
  }
}

const selectGirl = new SelectGirl(["ws", "ee", "qy"]);
console.log(selectGirl.getGirl(1));

4.4泛型默认值

当代码中没有直接指定,并且类型推论也没有成功时,默认值会生效

function say<T = any>(name: T):void {
  console.log(name)
}
say<string>('ws') // ok
say(true) // ok

5.命名空间namespace

命名空间这个语法,很类似编程中常说的模块化思想,比如webpack打包时,每个模块有自己的环境,不会污染其他模块,不会有全局变量产生。命名空间就跟这个很类似,注意这里是类似,而不是相同。

5.1.同一文件实现接口

 namespace API{
    export let obj={
        name:"哈哈",
    };
 
}
console.log(API.obj)

5.2 多个文件实现接口

导出的不能是值,只能是接口或者类,如果需要导出值,那么namespace同时也需要导出

  • 1.在a.ts中导出定义的接口
 namespace API{
    export interface Ishape{
        draw():void
    }
}
  • 2.在b.ts中可以实现这个接口
    draw:function(){
        console.log("draw")
    }
}
aa.draw();

5.3 直接导出值

  • 在a.ts中导出,这里不仅需要将接口和对象导出,也需要将namespace导出
export namespace API{
    export let obj={
        name:"哈哈",
    };
    export interface Ishape{
        draw():void
    }
}
console.log(API.obj)
  • 在b.ts中实现接口,并且导入在a.ts导出的namespace
//这里的路径一定要是相对路径
import {API} from "./a"
let aa:API.Ishape={
    draw:function(){
        console.log("draw")
    }
}
aa.draw();
console.log(API.obj)

导读

此篇文档总结ts的基础用法,还有高级用法还未总结,因为工作大量使用ts,因此乘着上班摸鱼
时间整理一下ts,温习一下ts的部分语法,仅供参考,本人菜鸡一枚,写文档纯属无聊,上班没事干