TypeScript(JavaScript的超集)
始于JavaScript,归于JavaScript
TypeScript从今天数以百万计的JavaScript开发者所熟悉的语法和语义开始。使用现有的JavaScript代码,包括流行的JavaScript库,并从JavaScript代码中调用TypeScript代码。
TypeScript可以编译出纯净、 简洁的JavaScript代码,并且可以运行在任何浏览器上、Node.js环境中和任何支持ECMAScript 3(或更高版本)的JavaScript引擎中
基础类型
TypeScript支持与JavaScript几乎相同的数据类型,
布尔值
let isDone: boolean = false;
数字
let decLiteral: number = ;
let hexLiteral: number = xf00d;
let binaryLiteral: number = b1010;
let octalLiteral: number = o744;
字符串
let name: string = "bob";
//模版字符串
let name: string = `Gene`;
let age: number = ;
let sentence: string = `Hello, my name is ${ name }.
数组
//1
let list: number[] = [, , ];
//2
let list: Array<number> = [, , ];
元组 Tuple
元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。 比如,你可以定义一对值分别为 string和number类型的元组。
// Declare a tuple type
let x: [string, number];
// Initialize it
x = ['hello', ]; // OK
// Initialize it incorrectly
x = [, 'hello']; // Error
当访问一个越界的元素,会使用联合类型替代
x = [10, ‘hello’,29]; //
枚举
像JAVA ,C#等其它语言一样,使用枚举类型可以为一组数值赋予友好的名字
enum Color {Red, Green, Blue};
let c: Color = Color.Green; //1
enum Color {Red = , Green, Blue};
let colorName: string = Color[];
alert(colorName);
任意值
有时候,我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。 这些值可能来自于动态的内容, 这种情况下,我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用 any类型来标记这些变量:
let notSure: any = ;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean
空值
当一个函数没有返回值时,你通常会见到其返回值类型是 void:
function warnUser(): void {
alert("This is my warning message");
}
//void类型的变量 只能为它赋予undefined和null:
let unusable: void = undefined;
函数
function buildName(firstName: string, lastName: string):string {
return firstName + " " + lastName;
}
let result1 = buildName("Bob"); // error, too few parameters
let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
let result3 = buildName("Bob", "Adams"); // ah, just right
Null 和 Undefined
let u: undefined = undefined;
let n: null = null;
let t: number = null;
类型断言
类型断言有两种形式。 其一是“尖括号”语法:
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;
接口
接口的作用就是为这些类型命名和为你的代码定义契约。
function printLabel(labelledObj: { label: string }) {
console.log(labelledObj.label);
}
let myObj = { size: , label: "Size 10 Object" };
printLabel(myObj);
//接口重写后
interface LabelledValue {
label: string;
}
function printLabel(labelledObj: LabelledValue) {
console.log(labelledObj.label);
}
let myObj = {size: , label: "Size 10 Object"};
printLabel(myObj);
可选属性
接口里的属性不全都是必需的。有些是只在某些条件下存在,或者根本不存在。 即给函数传入的参数对象中只有部分属性赋值了。
带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个?符号。可选属性的好处之一是可以对可能存在的属性进行预定义,
interface SquareConfig {
color?: string;
width?: number;
}
function createSquare(config: SquareConfig): {color: string; area: number} {
let newSquare = {color: "white", area: };
if (config.color) {
newSquare.color = config.color;
}
if (config.width) {
newSquare.area = config.width * config.width;
}
return newSquare;
}
let mySquare = createSquare({color: "black"});
函数类型
除了描述带有属性的普通对象外,接口也可以描述函数类型。为了使用接口表示函数类型,我们需要给接口定义一个调用签名。它就像是一个只有参数列表和返回值类型的函数定义。参数列表里的每个参数都需要名字和类型。
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
//函数的参数名不需要与接口里定义的名字相匹配
mySearch = function(source1: string, subString1: string) {
let result = source.search(subString);
if (result == -) {
return false;
}
else {
return true;
}
}
实现接口
与C#或Java里接口的基本作用一样,TypeScript也能够用它来明确的强制一个类去符合某种契约。
interface ClockInterface {
currentTime: Date;
setTime(d: Date); //return void
}
class Clock implements ClockInterface {
currentTime: Date;
setTime(d: Date) {
this.currentTime = d;
}
constructor(h: number, m: number) { }
}
接口继承
interface Shape {
color: string;
}
interface PenStroke {
penWidth: number;
}
interface Square extends Shape, PenStroke {
sideLength: number;
}
let square = <Square>{};
square.color = "blue";
square.sideLength = ;
square.penWidth = ;
类
继承
class Animal {
name:string;
constructor(theName: string) { this.name = theName; }
move(distanceInMeters: number = ) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
class Snake extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = ) {
console.log("Slithering...");
super.move(distanceInMeters);
}
}
class Horse extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = ) {
console.log("Galloping...");
super.move(distanceInMeters);
}
}
let sam = new Snake("Sammy the Python");
let tom = new Horse("Tommy the Palomino");
sam.move();
tom.move();
//Slithering...
//Sammy the Python moved 5m.
//Galloping...
//Tommy the Palomino moved 34m.
公共,私有与受保护的修饰符
默认为public
理解private
当成员被标记成private时,它就不能在声明它的类的外部访问
class Animal {
private name: string;
constructor(theName: string) { this.name = theName; }
}
new Animal("Cat").name; // Error: 'name' is private;
理解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());
readonly修饰符
你可以使用readonly关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化。
class Octopus {
readonly name: string;
readonly numberOfLegs: number = ;
constructor (theName: string) {
this.name = theName;
}
}
let dad = new Octopus("Man with the 8 strong legs");
dad.name = "Man with the 3-piece suit"; // error! name is readonly.