📚
note
Blog
  • Initial page
  • JS-notes
    • 使用浏览器书签执行js代码
    • JSON.stringify的小技巧
    • Fisher–Yates shuffle洗牌算法
    • 打印页面
  • Web-notes
    • 在网页中引入在线字体
  • Uniapp-notes
    • swiper-item高度自适应
    • 微信小程序的图片预览兼容性处理
  • VUE-notes
    • vue-note
    • vue3-note
  • VPS-notes
    • CentOs7笔记
    • ssh小记
    • Ubuntu笔记
    • vps安全相关
    • [Google Drive笔记](VPS-notes/Google Drive笔记.md)
  • TypeScript-notes
    • ts热编译项目
    • TypeScript笔记
    • js项目转ts
  • Python-notes
    • Python爬虫笔记
    • Python笔记
  • PHP-notes
    • php笔记
    • php+redis
    • php-codeIgniter
    • php抽奖算法
    • Laravel笔记
  • Mobile-notes
    • 移动端常用样式及兼容相关
  • Linux-notes
    • linux常用指令
  • Game-notes
    • Minecraft-server
  • TelegramBot-notes
    • tg-bot小记
  • Windows-notes
    • window-note
    • node-note
    • WSL-note
  • RaspberryPi-notes
    • RaspberryPi-note
    • 其他玩法
    • Openwrt
    • Ubuntu安装指南
  • Phone-notes
    • ZenFone6-note
  • Cocos-notes
    • Cocos-note
  • Network-notes
    • 单线复用
  • Other-notes
    • 国际化地域标识码
Powered by GitBook
On this page
  • 热编译
  • 基础类型
  • 布尔值(boolean)
  • 数字(number)
  • 字符串(string)
  • 数组
  • 元组
  • 枚举
  • any
  • void
  • null和undefined
  • never
  • object
  • 类型断言
  • 接口
  • 必选属性
  • 可选属性
  • 只读属性
  • 类
  • 类的继承
  • 类的属性私有化
  • 函数
  • 函数类型
  • 可选参数和默认参数
  • 剩余参数
  • 泛型
  • 泛型类
  • 泛型约束
  • 泛型里使用类类型
  • 枚举
  • 数字枚举
  • 字符串枚举
  • 异构枚举
  • 类型兼容性
  • 高级类型
  • 交叉类型(Intersection Types)
  • 联合类型(Union Types)
  • 类型保护与区分类型(Type Guards and Differentiation Types)
  • 可以为null的类型
  • 类型别名
  • 可辨识联合
  • 索引类型(Index types)
  • 迭代器与生成器
  • 迭代器
  • 生成器
  • 模块
  • 导出
  • 导入
  • export = 和 import = require()

Was this helpful?

  1. TypeScript-notes

TypeScript笔记

热编译

文件结构

project
│  gulpfile.js
│  package-lock.json
│  package.json
│  tsconfig.json
│  
├─dist
│      bundle.js
│      index.html
│      
├─node_modules
│
│
└─src
      greet.ts
      index.html
      main.ts
        

npm下包

npm install --save-dev browserify commonjs gulp gulp-typescript gulp-util tsify typescript vinyl-source-stream watchify

gulpfile.js

var gulp = require("gulp");
var browserify = require("browserify");
var source = require('vinyl-source-stream');
var tsify = require("tsify");
// 热更新
var watchify = require("watchify");
var gutil = require("gulp-util");
var paths = {
  pages: ['src/*.html']
};

gulp.task("copy-js", function () {
  return browserify({
      basedir: '.',
      debug: true,
      entries: ['src/main.ts'],
      cache: {},
      packageCache: {}
    })
    .plugin(tsify)
    .bundle()
    .pipe(source('main.js'))
    .pipe(gulp.dest("dist"));
});

var watchedBrowserify = watchify(browserify({
  basedir: '.',
  debug: true,
  entries: ['src/main.ts'],
  cache: {},
  packageCache: {}
}).plugin(tsify));

gulp.task("copy-html", function () {
  return gulp.src(paths.pages)
    .pipe(gulp.dest("dist"));
});

var bundle = function () {
  return watchedBrowserify
    .bundle()
    .pipe(source('bundle.js'))
    .pipe(gulp.dest("dist"));
}

gulp.task(bundle)


gulp.task('default', gulp.series('copy-html', 'bundle'));
watchedBrowserify.on("update", bundle);
watchedBrowserify.on("log", gutil.log);

tsconfig.json

{
    "files": [
        "src/main.ts",
        "src/greet.ts"
    ],
    "compilerOptions": {
        "noImplicitAny": true,
        "target": "es5"
    }
}

此时,在项目更目录使用gulp命令即可执行热编译。

基础类型

布尔值(boolean)

let isStr:boolean = false;

数字(number)

Typescript里所有的数字都是浮点数。支持十进制和十六进制的字面量,还支持ECMAScript 2015中引入的二进制和八进制字面量。

let decLiteral:number = 6;
let hexLiteral:number = 0xf00d;
let binaryLiteral:number = 0b1010;
let octalLiteral:number = 0o744;

字符串(string)

支持单、双引号以及模板字符串

let name:string = "bob";
let site:string = 'home';
let sentence:string =`My name is ${name}.I am at ${site} now.`

数组

// 第一种定义方法:在元素类型后面接上[]
let list:number[] = [1,2,3];

// 第二种定义方法:使用数组泛型
let arr:Array<number> = [1,2,3];

元组

先定义再使用

// 定义一个包含字符串和数字的元组
let x:[string,number,number];
// 初始化元组
x = ['hello',10,20];
// 初始化时必须要按照定义的时候写位置一一对应,否则报错。
x = [10,'hello',20]    //error

枚举

enum类型。使用枚举类型为一组数值赋予名字。

enum Color {red,green,blue}
let c:Color = Color.green;

默认情况下,元素编号从0开始,也可以设置为手动指定编号

enum Color {red=2,blue,green}
enum Color {red=2,blue=4,green=7}

枚举类型提供的一个便利是你可以由枚举的值得到它的名字。 例如,我们知道数值为2,但是不确定它映射到Color里的哪个名字,我们可以查找相应的名字:

enum Color {red = 1, green, bule}
let colorName: string = Color[2];
console.log(colorName);  // 'Green'

any

使用any定义不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查

let notSure:any = 4;
notSure = "string";
notSure = false;

void

void类型与any类型相反,表示没有任何类型。常见于函数没有返回值时,则其返回值类型是void。

function sayHi():void{
  console.log("Hi!~");
}

声明一个void类型的变量只能赋值undefined和null。

let unusable:void = undefined;

null和undefined

null和undefined类型对应的值就是unll和undefined。

never

never类型表示的是那些永不存在的值的类型。 例如, never类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型; 变量也可能是 never类型,当它们被永不为真的类型保护所约束时。

// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
    throw new Error(message);
}

object

object表示非原始类型,也就是除number,string,boolean,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

类型断言

使用类型断言能让编译器知道你已经对类型进行了必须的检查,它不会再对数据进行检查和解构。

类型断言有两种形式。 其一是“尖括号”语法:

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;

两种形式是等价的。 至于使用哪个大多数情况下是凭个人喜好;

然而,当你在TypeScript里使用JSX时,只有 as语法断言是被允许的。

接口

TypeScript的核心原则之一是对值所具有的结构进行类型检查。

必选属性

使用interface定义一个接口,将这个接口作为类型传入函数,则对这个函数进行传参时需要有对应类型的值

interface LabelledValue {
  label: string;
}

function printLabel(labelledObj: LabelledValue) {
  console.log(labelledObj.label);
}

let myObj = {size: 10, label: "Size 10 Object"};
printLabel(myObj); // Size 10 Object

可选属性

带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个?符号。

interface SquareConfig {
  color?: string;
  width?: number;
}

function createSquare(config: SquareConfig): {color: string; area: number} {
  let newSquare = {color: "white", area: 100};
  if (config.color) {
    newSquare.color = config.color;
  }
  if (config.width) {
    newSquare.area = config.width * config.width;
  }
  return newSquare;
}

let mySquare = createSquare({color: "black"});

只读属性

定义接口时,在属性吗赢钱加readonly来指定只读属性。

interface Point {
  readonly x:number;
  readonly y:number;
}

对象赋值后就不能再改变了

let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error!

TypeScript具有ReadonlyArray<T>类型,数组创建后就不能再改变了

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!

上面代码的最后一行,可以看到就算把整个ReadonlyArray赋值到一个普通数组也是不可以的。 但是你可以用类型断言重写:

a = ro as number[];

readonly vs const

最简单判断该用readonly还是const的方法是看要把它做为变量使用还是做为一个属性。 做为变量使用的话用const,若做为属性则使用readonly。

类

类的实现

class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}

let greeter = new Greeter("world");

类的继承

class Animal {
    move(distanceInMeters: number = 0) {
        console.log(`Animal moved ${distanceInMeters}m.`);
    }
}

class Dog extends Animal {
    bark() {
        console.log('Woof! Woof!');
    }
}

const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();

类从基类中继承了属性和方法。 这里, Dog是一个 派生类,它派生自 Animal 基类,通过 extends关键字。 派生类通常被称作 子类,基类通常被称作 超类。

类的属性私有化

TypeScript里,成员都默认为 public。即所有成员默认可见。

理解 private

当成员被标记成 private时,它就不能在声明它的类的外部访问。比如:

class Animal {
    private name: string;
    constructor(theName: string) { this.name = theName; }
}

new Animal("Cat").name; // 错误: 'name' 是私有的.

理解 protected

protected修饰符与 private修饰符的行为很相似,但有一点不同, protected成员在派生类中仍然可以访问。

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); // 错误

readonly修饰符

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

class Octopus {
    readonly name: string;
    readonly numberOfLegs: number = 8;
    constructor (theName: string) {
        this.name = theName;
    }
}
let dad = new Octopus("Man with the 8 strong legs");
dad.name = "Man with the 3-piece suit"; // 错误! name 是只读的.

存取器

TypeScript支持通过getters/setters来截取对对象成员的访问。 它能帮助你有效的控制对对象成员的访问。

let passcode = "secret passcode";

class Employee {
    private _fullName: string;

    get fullName(): string {
        return this._fullName;
    }

    set fullName(newName: string) {
        if (passcode && passcode == "secret passcode") {
            this._fullName = newName;
        }
        else {
            console.log("Error: Unauthorized update of employee!");
        }
    }
}

let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
    alert(employee.fullName);
}

静态属性

当类被实例化的时候才会被初始化的属性。 创建类的静态成员,这些属性存在于类本身上面而不是类的实例上。

在这个例子里,我们使用 static定义 origin,因为它是所有网格都会用到的属性。 每个实例想要访问这个属性的时候,都要在 origin前面加上类名。 如同在实例属性上使用 this.前缀来访问属性一样,这里我们使用 Grid.来访问静态属性。

class Grid {
    static origin = {x: 0, y: 0};
    calculateDistanceFromOrigin(point: {x: number; y: number;}) {
        let xDist = (point.x - Grid.origin.x);
        let yDist = (point.y - Grid.origin.y);
        return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
    }
    constructor (public scale: number) { }
}

let grid1 = new Grid(1.0);  // 1x scale
let grid2 = new Grid(5.0);  // 5x scale

console.log(grid1.calculateDistanceFromOrigin({x: 10, y: 10}));
console.log(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));

函数

函数类型

给函数添加类型检查

function add(x: number, y: number): number {
    return x + y;
}

let myAdd = function(x: number, y: number): number { return x + y; };
let myAdd: (x: number, y: number) => number =
    function(x: number, y: number): number { return x + y; };

可选参数和默认参数

JavaScript里,每个参数都是可选的,可传可不传。 没传参的时候,它的值就是undefined。 在TypeScript里我们可以在参数名旁使用 ?实现可选参数的功能。 比如,我们想让last name是可选的:

function buildName(firstName: string, lastName?: string) {
    if (lastName)
        return firstName + " " + lastName;
    else
        return firstName;
}

let result1 = buildName("Bob");  // works correctly now
let result2 = buildName("Bob", "Adams", "Sr.");  // error, too many parameters
let result3 = buildName("Bob", "Adams");  // ah, just right

可选参数必须跟在必须参数后面。 如果上例我们想让first name是可选的,那么就必须调整它们的位置,把first name放在后面。

剩余参数

必要参数,默认参数和可选参数有个共同点:它们表示某一个参数。 有时,你想同时操作多个参数,或者你并不知道会有多少参数传递进来。 在JavaScript里,你可以使用 arguments来访问所有传入的参数。

在TypeScript里,你可以把所有参数收集到一个变量里:

function buildName(firstName: string, ...restOfName: string[]) {
  return firstName + " " + restOfName.join(" ");
}

let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");

剩余参数会被当做个数不限的可选参数。 可以一个都没有,同样也可以有任意个。 编译器创建参数数组,名字是你在省略号( ...)后面给定的名字,你可以在函数体内使用这个数组。

这个省略号也会在带有剩余参数的函数类型定义上使用到:

function buildName(firstName: string, ...restOfName: string[]) {
  return firstName + " " + restOfName.join(" ");
}

let buildNameFun: (fname: string, ...rest: string[]) => string = buildName;

泛型

  1. 在程序编码中一些包含类型参数的类型,也就是说泛型的参数只可以代表类,不能代表个别对象。(这是当今较常见的定义)

一句话概况就是:使用泛型来创建可重用且支持多种类型的数据组件。

定义一个泛型函数

function identity<T>(arg: T): T {
    return arg;
}

泛型的使用方法有两种:

第一种:传入所有参数,包含类型参数:

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

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

类型推论: 即编译器会根据传入的参数自动地帮助我们确定T的类型

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

泛型类

将泛型定义在类中:

class GenericNumber<T> {
    zeroValue: T;
    add: (x: T, y: T) => T;
}

let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };

泛型约束

定义一个接口来描述约束条件,比如说泛型里需要处理带有.length属性的所有类型,只要传入有这个类型的属性,则不报错。

interface Lengthwise {
    length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);  // Now we know it has a .length property, so no more error
    return arg;
}

泛型里使用类类型

class BeeKeeper {
    hasMask: boolean;
}

class ZooKeeper {
    nametag: string;
}

class Animal {
    numLegs: number;
}

class Bee extends Animal {
    keeper: BeeKeeper;
}

class Lion extends Animal {
    keeper: ZooKeeper;
}

function createInstance<A extends Animal>(c: new () => A): A {
    return new c();
}

createInstance(Lion).keeper.nametag;  // typechecks!
createInstance(Bee).keeper.hasMask;   // typechecks!

枚举

使用枚举我们可以定义一些带名字的常量。 使用枚举可以清晰地表达意图或创建一组有区别的用例。 TypeScript支持数字的和基于字符串的枚举。

数字枚举

定义了一个数字枚举, Up使用初始化为 1。 其余的成员会从 1开始自动增长。 换句话说,Direction.Up的值为 1, Down为 2, Left为 3, Right为 4

如果不对枚举成员使用初始化,则将会从0开始。

enum Direction {
    Up = 1,
    Down,
    Left,
    Right
}

字符串枚举

在一个字符串枚举里,每个成员都需要使用字符串字面量

enum Direction{
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT"
}

异构枚举

枚举可以混合字符串和数字成员,但是并不推荐这样做

enum isBook{
  No = 0,
  Yes = "YES",
}

类型兼容性

高级类型

交叉类型(Intersection Types)

联合类型(Union Types)

下面是一个联合类型的例子

function(x: string, y: string | number){
  return x + y
}

联合类型表示一个值可以是几种类型之一,使用|分隔每个类型。

如果一个值是联合类型,那只能访问这个类型里的成员

interface Bird {
    fly();
    layEggs();
}

interface Fish {
    swim();
    layEggs();
}

function getSmallPet(): Fish | Bird {
    // ...
}

let pet = getSmallPet();
pet.layEggs(); // okay
pet.swim();    // errors

类型保护与区分类型(Type Guards and Differentiation Types)

套用上面的一段代码,当我们想判断pet是否为Fish时,我们需要在判断语句里额外添加类型断言。

let pet = getSmallPet();

if ((<Fish>pet).swim) {
    (<Fish>pet).swim();
}
else {
    (<Bird>pet).fly();
}

用户自定义类型保护

要自定义一个类型保护,需要定义一个函数,返回一个类型谓词

类型谓词:parameterName is Type,其中parameterName必须是当前函数签名里的一个参数名。

function isFish(pet: Fish | Bird): pet is Fish {
    return (<Fish>pet).swim !== undefined;
}

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}'.`);
}

typeof类型保护只有两种形式能被识别:typeof v === "typename"和 typeof v !== "typename",

可以为null的类型

默认情况下,类型检查器认为 null与 undefined可以赋值给任何类型。null与 undefined是所有其它类型的一个有效值。 这也意味着,你阻止不了将它们赋值给其它类型,就算是你想要阻止这种情况也不行

--strictNullChecks标记可以解决此错误:当你声明一个变量时,它不会自动地包含 null或 undefined。 你可以使用联合类型明确的包含它们:

let s = "foo";
s = null; // 错误, 'null'不能赋值给'string'
let sn: string | null = "bar";
sn = null; // 可以
sn = undefined; // error, 'undefined'不能赋值给'string | null'

可选参数与可选属性

使用了 --strictNullChecks,可选参数和可选属性都会被自动地加上 | undefined:

function f(x: number, y?: number) {
    return x + (y || 0);
}
f(1, 2);
f(1);
f(1, undefined);
f(1, null); // error, 'null' is not assignable to 'number | undefined'

class C {
    a: number;
    b?: number;
}
let c = new C();
c.a = 12;
c.a = undefined; // error, 'undefined' is not assignable to 'number'
c.b = 13;
c.b = undefined; // ok
c.b = null; // error, 'null' is not assignable to 'number | undefined'

类型别名

类型别名会给一个类型起个新名字。 类型别名有时和接口很像,但是可以作用于原始值,联合类型,元组以及其它任何你需要手写的类型。

type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
    if (typeof n === 'string') {
        return n;
    }
    else {
        return n();
    }
}

可辨识联合

声明联合接口:

interface Square {
    kind: "square";
    size: number;
}
interface Rectangle {
    kind: "rectangle";
    width: number;
    height: number;
}
interface Circle {
    kind: "circle";
    radius: number;
}

首先我们声明了将要联合的接口。 每个接口都有 kind属性但有不同的字符串字面量类型。 kind属性称做 可辨识的特征或 标签。 其它的属性则特定于各个接口。 注意,目前各个接口间是没有联系的。 下面我们把它们联合到一起:

type Shape = Square | Rectangle | Circle;

现在我们使用可辨识联合:

function area(s: Shape) {
    switch (s.kind) {
        case "square": return s.size * s.size;
        case "rectangle": return s.height * s.width;
        case "circle": return Math.PI * s.radius ** 2;
    }
}

索引类型(Index types)

通过 索引类型查询和 索引访问操作符:

function pluck<T, K extends keyof T>(o: T, names: K[]): T[K][] {
  return names.map(n => o[n]);
}

interface Person {
    name: string;
    age: number;
}
let person: Person = {
    name: 'Jarid',
    age: 35
};
let strings: string[] = pluck(person, ['name']); // ok, string[]

编译器会检查 name是否真的是 Person的一个属性。 本例还引入了几个新的类型操作符。 首先是 keyof T, 索引类型查询操作符。 对于任何类型 T, keyof T的结果为 T上已知的公共属性名的联合。 例如:

let personProps: keyof Person; // 'name' | 'age'

迭代器与生成器

迭代器

for..of vs. for..in 语句

for..of和for..in均可迭代一个列表;但是用于迭代的值却不同,for..in迭代的是对象的 键 的列表,而for..of则迭代对象的键对应的值。

下面的例子展示了两者之间的区别:

let list = [4, 5, 6];

for (let i in list) {
    console.log(i); // "0", "1", "2",
}

for (let i of list) {
    console.log(i); // "4", "5", "6"
}

生成器

目标为 ES5 和 ES3

当生成目标为ES5或ES3,迭代器只允许在Array类型上使用。 在非数组值上使用 for..of语句会得到一个错误,就算这些非数组值已经实现了Symbol.iterator属性。

编译器会生成一个简单的for循环做为for..of循环,比如:

let numbers = [1, 2, 3];
for (let num of numbers) {
    console.log(num);
}

生成的代码为:

var numbers = [1, 2, 3];
for (var _i = 0; _i < numbers.length; _i++) {
    var num = numbers[_i];
    console.log(num);
}

目标为 ECMAScript 2015 或更高

当目标为兼容ECMAScipt 2015的引擎时,编译器会生成相应引擎的for..of内置迭代器实现方式。

模块

模块在其自身的作用域里执行,而不是在全局作用域里;这意味着定义在一个模块里的变量,函数,类等等在模块外部是不可见的,除非你明确地使用export形式之一导出它们。 相反,如果想使用其它模块导出的变量,函数,类,接口等的时候,你必须要导入它们,可以使用 import形式之一。

导出

导出声明

任何声明(比如变量,函数,类,类型别名或接口)都能够通过添加export关键字来导出。

export interface StringValidator {
    isAcceptable(s: string): boolean;
}

导出语句

class ZipCodeValidator implements StringValidator {
    isAcceptable(s: string) {
        return s.length === 5 && numberRegexp.test(s);
    }
}
export { ZipCodeValidator };
export { ZipCodeValidator as mainValidator };

重新导出

我们经常会去扩展其它模块,并且只导出那个模块的部分内容。 重新导出功能并不会在当前模块导入那个模块或定义一个新的局部变量。

export class ParseIntBasedZipCodeValidator {
    isAcceptable(s: string) {
        return s.length === 5 && parseInt(s).toString() === s;
    }
}

// 导出原先的验证器但做了重命名
export {ZipCodeValidator as RegExpBasedZipCodeValidator} from "./ZipCodeValidator";

或者一个模块可以包裹多个模块,并把他们导出的内容联合在一起通过语法:export * from "module"。

export * from "./StringValidator"; // exports interface StringValidator
export * from "./LettersOnlyValidator"; // exports class LettersOnlyValidator
export * from "./ZipCodeValidator";  // exports class ZipCodeValidator

默认导出

每个模块都可以有一个default导出。 默认导出使用 default关键字标记;并且一个模块只能够有一个default导出。 需要使用一种特殊的导入形式来导入 default导出。

类和函数声明可以直接被标记为默认导出。 标记为默认导出的类和函数的名字是可以省略的。

export default class ZipCodeValidator {
    static numberRegexp = /^[0-9]+$/;
    isAcceptable(s: string) {
        return s.length === 5 && ZipCodeValidator.numberRegexp.test(s);
    }
}

导入

模块的导入操作与导出一样简单。 可以使用以下 import形式之一来导入其它模块中的导出内容。

导入一个模块中的某个导出内容

import { ZipCodeValidator } from "./ZipCodeValidator";

let myValidator = new ZipCodeValidator();

可以对导入内容重命名

import { ZipCodeValidator as ZCV } from "./ZipCodeValidator";
let myValidator = new ZCV();

将整个模块导入到一个变量,并通过它来访问模块的导出部分

import * as validator from "./ZipCodeValidator";
let myValidator = new validator.ZipCodeValidator();

具有副作用的导入模块

尽管不推荐这么做,一些模块会设置一些全局状态供其它模块使用。 这些模块可能没有任何的导出或用户根本就不关注它的导出。 使用下面的方法来导入这类模块:

import "./my-module.js";

export = 和 import = require()

CommonJS和AMD的环境里都有一个exports变量,这个变量包含了一个模块的所有导出内容。

CommonJS和AMD的exports都可以被赋值为一个对象, 这种情况下其作用就类似于 es6 语法里的默认导出,即 export default语法了。虽然作用相似,但是 export default 语法并不能兼容CommonJS和AMD的exports。

为了支持CommonJS和AMD的exports, TypeScript提供了export =语法。

export =语法定义一个模块的导出对象。 这里的对象一词指的是类,接口,命名空间,函数或枚举。

若使用export =导出一个模块,则必须使用TypeScript的特定语法import module = require("module")来导入此模块。

Last updated 2 years ago

Was this helpful?

的定义主要有以下两种:

在程序编码中一些包含参数的。其参数可以代表类或对象等等。(现在人们大多把这称作)

泛型
类
模板