TypeScipt学习笔记(未完待续)

这篇文章是TypeScript的学习笔记,主要内容来自TypeScript官网的handbook

基础类型

TypeScript提供了如下类型:

  • booleanBool类型;
  • number数字类型(包括整数和浮点数);
  • string字符串类型;
  • type[]Array<type>数组,其中type是某一类型,下同;
  • [type1, type2, ...]元组,对元组的下标索引会得到对应的类型,越界会报错;
  • enum Type {value1, value2, ...}中的Type枚举,通过Type.value来访问枚举值对应的整型,类似C语言,可以为枚举设置不同的整型值,也可通过Type[index]来访问整型对应的枚举值字符串;
  • any任意类型,与Object类型类似(注意大写),但Object类型只允许被赋予任意值,但不能访问任意属性和方法;
  • void:用于函数返回值表示不返回值,对于void变量,则只能赋值undefined或者null--strictNullChecks不开启);
  • undefinednull:与同名的值对应,默认情况下它们是所有其他类型的子类型,但--strictNullChecks开启时,它们只能赋值给any或者对应的类型或者undefined赋值给void
  • never:用于函数返回值类型,表示函数始终不返回(如抛异常),它是任意类型的子类型,但不是其他类型的父类型,即使是any也不能赋值给never
  • object:(注意小些)代表所有非原始数据类型的类型。

类型断言是告知编译器相信程序员所指定的类型,有两种等价的形式:<type>valuevalue as type。在使用JSX的时候只有第二种形式可用。

变量声明

与JavaScript相同,var有函数级作用域,可被定义多次;而let有块作用域,不能屏蔽同作用域同名变量。const的变量不能修改,但可以修改其成员。TypeScript支持数组解构(包括let [first, ...rest] = [1, 2, 3, 4];或省略部分元素)、元组解构(类似于数组)和对象解构(支持...剩余语法、属性重命名let { a: newName } = o;、默认值let { a = 1001 } = o)。此外还支持解构相反的传播语法,如[0, ...first, ...second, 5]{ ...defaults, food: "rich" }

接口

使用如下语法定义接口:

interface Name {
  property: Type1;
  optionalProperty?: Type2;
  readonly ReadonlyProperty?: Type3;
  // 如果允许包含其他属性
  [propName: string]: any;
}

也可以用这样的类型代替接口{ property: Type1, optionalProperty?: Type2 }

TypeScript还有ReadonlyArray<T>这种数组类型,只是可变方法都移除了。

此外还可以创建函数接口,其中参数名不必匹配:

interface Func {
  // 函数类型
  (param1: Type1, param2: Type2): Type3;
}

此外也可以创建数组接口:

interface StringArray {
  [index: number]: string;
}

类可以实现接口,如下:

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) { }
}

但注意一个类实现一个接口的时候,只有实例是检查的,而静态方法不检查。而类的构造函数属于静态方法,只有当把类作为实例的时候才能检查其构造函数。

此外还可以用extends关键字扩展接口。对于一个接口可以扩展多个接口。

总的来说TypeScript里的类和JavaScript的类似,这里着重于不同之处。TypeScript的类的字段要显式声明。子类构造函数必须调用super()。成员可以有访问权限public(默认)、privateprotected。可以有readonly字段,必须由构造函数或声明处初始化。

此外还有抽象类,如下:

abstract class Animal {
  abstract makeSound(): void;
  move(): void {
    console.log("roaming the earth...");
  }
}

接口也可以继承类。

函数

函数类型为(param1: type1, param: type2, ...) => returnType。可选参数必须在必选参数的后面。可以对this参数加类型注解,确保它是某种类型。可以对一个函数的类型进行重载(不包括定义),如下:

let suits = ["hearts", "spades", "clubs", "diamonds"];

function pickCard(x: {suit: string; card: number; }[]): number;
function pickCard(x: number): {suit: string; card: number; };
function pickCard(x): any {
  // Check to see if we're working with an object/array
  // if so, they gave us the deck and we'll pick the card
  if (typeof x == "object") {
    let pickedCard = Math.floor(Math.random() * x.length);
    return pickedCard;
  }
  // Otherwise just let them pick the card
  else if (typeof x == "number") {
    let pickedSuit = Math.floor(x / 13);
    return { suit: suits[pickedSuit], card: x % 13 };
}
}

注意function pickCard(x): any不是重载的一部分。

泛型

可以给函数添加类型变量,创建泛型函数:

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

调用时,如果泛型是函数参数,可以省略模板参数。上述的函数,其类型写下来是<U>(arg: U) => U。此外在类名后面也可以添加类型变量,构成泛型类。

类似Java,类型变量可以有类型约束如<T extends someType>

枚举

数字枚举如上所示,此外也可以有字符串枚举或者混合的。还有const枚举,形如const enum Enum { ... },它会彻底在编译时移除,只能含有编译期计算的值。

类型推导

(未完待续)

编辑本页

孙子平
孙子平
静态分析方向研究生
下一页
上一页

相关