软件工程师,TypeScript值得你拥有

背景

         □ TypeScript起源于使用JavaScript开发的大型项目。由于JavaScript语言本身的局限性,难以胜任和维护大型项目开发,因此微软开发了TypeScript,使得其能够胜任开发大型项目。

        □ TypeScript是微软开发的一个开源的编程语言,通过在JavaScript的基础上添加静态类型定义构建而成。TypeScript通过TypeScript编译器或Babel转译为JavaScript代码,可运行于任何浏览器,任何操作系统。

        □ 2012年10月,微软发布了首个公开版本的TypeScript。2013年6月19日,在经历了一个预览版之后,微软发布了正式版的TypeScript。

        □ TypeScript的作者是安德斯·海尔斯伯格,他也是C#的首席架构师。

特性

        TypeScript是一种给JavaScript添加特性的语言扩展,是JavaScript 的一个超集。

类型批注

        □ 布尔值

let isDone: boolean = false;

        □ 数字

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

        □ 字符串

let name: string = "bob";

        □ 数组

let list: number[] = [1, 2, 3];
let list: Array<number> = [1, 2, 3];

        □ 元组tuple

let x: [string, number] = ['hello', 10]; 

        □ 枚举

enum Color {Red = 1, Green = 2, Blue = 4}
let c: Color = Color.Green;
let colorName: string = Color[2];
alert(colorName); 

        □ 任意值

let notSure: any = 4;
notSure = true;
let list: any[] = [1, true, "free"];
list[1] = 100;

        □ 空值

function func(): void {
    alert("hello world");
}
// void类型的变量只能被赋值成undefined和null
let unusable: void = undefined;

        □ null和undefined

let a: undefined = undefined;
let b: null = null;

        默认情况下,null和undefined是所有类型的子类型,也就是说,你可以把null和undefined赋值给number类型的变量。但当你指定了--strictNullChecks标记,null和undefined只能赋值给void和它们自身,这能避免很多常见的问题。

        □ 联合类型

        联合类型表示一个值可以是几种类型之一。 我们用竖线(|)分隔每个类型,所以number | string | boolean表示一个值可以是number,string,或boolean。

        如果一个值是联合类型,我们只能访问此联合类型的所有类型里共有的成员。

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

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

function getSmallPet(): Fish | Bird {}

let pet = getSmallPet();
pet.layEggs();
// 不是共有成员,会报错
pet.swim();

        □ 类型转换(类型断言)

        方式1:

let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;

        方式2:

let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;

        两种形式是等价的,至于使用哪个,大多数情况下是凭个人喜好。在TypeScript里使用JSX时,只有as语法是被允许的。

接口

        □ 接口定义

interface ConfigOptions {
   // 必须带的属性
  color: string;
  // 可选属性
  width?: number;
  // 只读属性
  readonly x: number;
  // 函数类型
  setTime(d: Date);
}

interface ConfigOptions2 {
    color: string;
    // 字符串索引签名(可以有任意数量的其他属性)
    [propName: string]: any;
}

interface StringArray {
  // 数字索引签名
  [index: number]: string;
}

let myArray: StringArray;
myArray = ["Bob", "Fred"];
let myStr: string = myArray[0];

        □ 接口使用

function create(config: ConfigOptions) {
}

create({ colour: "red", width: 100, x: 2 });
create({ colour: "red", width: 100, x: 2 } as ConfigOptions);

        □ 继承接口

interface Shape {
    color: string;
}

interface Square extends Shape {
    len: number;
}

        □ 类的定义

class Greeter {
    greeting: string;
    // 只读属性必须在声明时或构造函数里被初始化
    readonly name: string;
    readonly numberOfLegs: number = 8;
    constructor(message: string, name: string) {
        this.greeting = message;
        this.name = name;
    }
    greet() {
        return "Hello, " + this.greeting;
    }
}

        □ 参数属性

        参数属性通过给构造函数参数添加一个访问限定符来声明。使用private限定一个参数属性会声明并初始化一个私有成员,对于public和protected来说也是一样。

class Animal {
    constructor(private name: string) { }

    move(distanceInMeters: number) {
        console.log(${this.name} moved ${distanceInMeters}m.);
    }
}

        □ 存取器

        通过getters/setters来截取对对象成员的访问

class Employee {
    private _fullName: string;
    get fullName(): string {
        return this._fullName;
    }
    set fullName(newName: string) {
        this._fullName = newName;
    }
}

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

        □ 类的继承

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

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

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

        □ 抽象类

abstract class Department {
    constructor(public name: string) {
    }
    abstract printMeeting(): void; // 必须在派生类中实现
}

class AccountingDepartment extends Department {
    constructor() {
        super('Accounting and Auditing');
    }
    printMeeting(): void {
        console.log('The Accounting Department meets each Monday at 10am.');
    }
}

模块

        □ 从ECMAScript 2015开始,JavaScript引入了模块的概念,TypeScript也沿用了这个概念。

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

        □ 模块是自声明的,两个模块之间的关系是通过在文件级别上使用import和export建立的。

export
export as
export default
import
import as
import default

泛型

        □ 设计一个函数echo,这个函数会返回任何传入它的值。

function echo(arg: number): number {
    return arg;
}

function echo(arg: any): any {
    return arg;
}

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

let output = echo<string>("myString");
let output = echo("myString");

        □ 使用泛型创建泛型函数时,编译器要求你在函数体内必须正确使用这个通用的类型。换句话说,你必须把这些参数当作是任意或所有类型。

function echo<T>(arg: T): T {
    console.log(arg.length);
    return arg;
}

function echo<T>(arg: T[]): T[] {
    console.log(arg.length);
    return arg;
}

let myEcho: <T>(arg: T) => T = echo;

        □ 泛型类

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

let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;

let stringNumeric = new GenericNumber<string>();
stringNumeric.zeroValue = "hello";

        □ 泛型约束

interface Lengthwise {
    length: number;
}

function echo<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);
    return arg;
}

// 约束不通过
echo(3);
// 约束通过
echo({length: 10, value: 3});

function getProperty<T, K extends keyof T>(obj: T, key: K) {
    return obj[key];
}

let x = { a: 1, b: 2, c: 3, d: 4 };

// 约束通过
getProperty(x, "a");
// 约束不通过
getProperty(x, "m");

        □ 类类型(使用泛型创建工厂函数时,需要引用构造函数的类类型)

class Animal {
    numLegs: number;
}

class Bee extends Animal {
    name1: string;
}

class Lion extends Animal {
    name2: string;
}

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

alert(createInstance(Lion).name2)

猜你喜欢

转载自blog.csdn.net/hope_wisdom/article/details/131615811