TypeScript 速查
by Ash Norseman
基本类型
Boolean
let isDone: boolean = false;
Number
let decimal: number = 6;
String
let color: string = 'blue';
let fullName: string = 'Bob Bobbington';
let sentence: string = `Hello, my name is ${fullName}.`
Array
let list: number[] = [1, 2, 3];
Enum
enum Color {Red, Green, Blue};
let c: Color = Color.Green;
enum Color {Red = 1, Green, Blue};
let colorName: string = Color[2]; // 'Green'
Any
let notSure: any = 4;
notSure = 'maybe a string instead';
notSure = false;
let list: any[] = [1, true, "free"];
对比:Object 类型可以任意赋值,但不能调用方法。
let notSure: any = 4;
notSure.ifItExists();
notSure.toFixed();
let prettySure: Object = 4;
prettySure.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object'.
Void
function warnUser(): void {
alert('This is my warning message');
}
Null and Undefined
let u: undefined = undefined;
let n: null = null;
默认情况下,null 和 undefined 是其他类型的子类型。也就是说,可以把 null 或 undefined 赋值给其他类型的变量。开启 --strictNullChecks
禁用上述规则。
Never
function error(message: string): never {
throw new Error(message);
}
function fail() {
return error('Something failed');
}
function infiniteLoop(): never {
while (true) { }
}
Type assertions
类似于其他语言的「类型转换」,但仅仅起到告知编译器的作用,对代码执行本身没有任何影响。
let someValue: any = 'this is a string';
let strLength: number = (<string>someValue).length;
// JSX 环境下使用如下语法:
let someValue: any = 'this is a string';
let strLength: number = (someValue as string).length;
Interfaces
定义变量的「形状」。
interface LabelledValue {
label: string;
}
function printLabel(labelledObj: LabelledValue) {
console.log(labelledObj.label);
}
let myObj = { size: 10, label: 'Size 10 Object' };
printLabel(myObj);
使用未定义的属性会报错,防止拼写错误。如上述代码中拼错 label:labelledObj. lable
,编译器会报错。
可省略的属性
interface SquareConfig {
color?: string;
width?: number;
}
function createSquare(config: SquareConfig): { color: string; area: number } {
// ...
}
let mySquare = createSquare({ color: 'black' });
只读属性
interface Point {
readonly x: number;
readonly y: number;
}
let p1: Point = { x: 10, y: 20 };
p1.x = 5; // Error!
只读数组:不允许对数组做任何操作,包括修改和增删元素。
let ro: ReadonlyArray<number> = a;
绕过类型检测的方式
Type assertion:
let mySquare = createSquare(<SquareConfig>{ width: 100, opacity: 0.5 });
或者定义允许其他任意属性:
interface SquareConfig {
color?: string;
width?: number;
[propName: string]: any;
}
Function Types
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(src, sub) {
// ...
}
Indexable Types
index 支持 number 和 string 类型。
interface StringArray {
[index: number]: string;
}
let myArray: StringArray;
myArray = ['Bob', 'Fred'];
let myStr: string = myArray[0];
number 类型必须是 string 类型的子类型。
class Animal {
name: string;
}
class Dog extends Animal {
breed: string;
}
// Error: indexing with a 'string' will sometimes get you a Dog!
interface NotOkay {
[x: number]: Animal;
[x: string]: Dog;
}
只读:
interface ReadonlyStringArray {
readonly [index: number]: string;
}
let myArray: ReadonlyStringArray = ['Alice', 'Bob'];
myArray[2] = 'Mallory'; // error!
Class Types
Interface 只能定义 class 的 public 属性和方法。
interface ClockInterface {
currentTime: Date;
setTime(d: Date);
}
class Clock implements ClockInterface {
currentTime: Date;
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) { }
}
Interface 的扩展
interface Shape {
color: string;
}
interface PenStroke {
penWidth: number;
}
interface Square extends Shape, PenStroke {
sideLength: number;
}
let square = <Square>{};
square.color = 'blue';
square.sideLength = 10;
square.penWidth = 5.0;
混合类型
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter {
let counter = <Counter>function (start: number) { };
counter.interval = 123;
counter.reset = function () { };
return counter;
}
let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;
类
Public、private 和 protected 修饰符
默认属性:public
。
private
:无法外部调用。
class Animal {
private name: string;
constructor(theName: string) { this.name = theName; }
}
new Animal('Cat').name; // Error: 'name' is private;
protacted
:继承类的实例可以调用,但无法外部调用。
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;
}
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); // error
只读属性
class Octopus {
readonly name: string;
constructor (theName: string) {
this.name = theName;
}
}
快速定义属性
给 constructor 的参数加上修饰符,省去属性定义。
class SomeClass {
constructor(
private a: string,
protacted b: string,
public c: string,
readonly d: string
) { }
}
抽象类
abstract class Animal {
abstract makeSound(): void;
move(): void {
console.log('roaming the earth...');
}
}
抽象类中的抽象方法不需要具体实现,实现代码写在继承它的类里。
class Cat extends Animal {
constructor(public name: string) { }
makeSound(): void {
console.log('meow');
}
move(): void {
super();
console.log('cat is moving...');
}
}
函数
函数类型
function add(x: number, y: number): number {
return x + y;
}
let myAdd = function(x: number, y: number): number { return x + y; };
可省略参数
function buildName(firstName: string, lastName?: string): string {
// ...
}
let result1 = buildName('Bob');
let result3 = buildName('Bob', 'Adams');
let result2 = buildName('Bob', 'Adams', 'Sr.'); // error, too many parameters
默认参数
function buildName(firstName: string, lastName = 'Smith') {
// ...
}
Rest 参数
function buildName(firstName: string, ...restOfName: string[]): string {
return `${firstName} ${restOfName.join(' ')}`;
}
let employeeName = buildName('Joseph', 'Samuel', 'Lucas', 'MacKinzie');
重载
function pickCard(x: number[]): number;
function pickCard(x: number): Card;
function pickCard(x): any {
if (typeof x == "object") {
// ...
} else if (typeof x == "number") {
// ...
}
}
注意:以上代码中的 function pickCard(x): any
并不是重载的定义。
Generics
T
表示用户在调用时指定的类型。
function identity<T>(arg: T): T {
return arg;
}
let output = identity<string>('myString');
Generic Array
function loggingIdentity<T>(arg: T[]): T[] {
console.log(arg.length); // Array has a .length, so no more error
return arg;
}
Generic Classes
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; };
限制范围
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;
}
指定泛型之间的依赖:
function copyFields<T extends U, U>(target: T, source: U): T {
// ...
}
let x = { a: 1, b: 2, c: 3, d: 4 };
copyFields(x, { b: 10, d: 20 });
copyFields(x, { Q: 90 }); // error: property 'Q' isn't declared in 'x'.