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'.