环境配置
- sudo npm install typescript -g
- tsc greeter.ts
类型注解
接口 - 定义类的样子
- 理解: 如果两个类型其内部结构兼容(如: 猫,狗都有毛,和四条腿), 那么这些兼容特性, 就可以实现一个接口
可选属性 ?
可选属性的好处之一是可以对可能存在的属性进行预定义,好处之二是可以捕获引用了不存在的属性时的错误
只读属性
interface Point {
readonly x: number;
readonly y: number;
}
接口继承和混合类型
- 接口继承
interface interfaceA {
a:number;
}
interface interfaceB {
b:string;
}
interface interfaceC extends interfaceA,interfaceB {
c:boolean;
}
let interC:interfaceC = <interfaceC>{};
interC.a = 100;
interC.b = "lsw";
interC.c = true;
- 混合类型
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
var c: Counter;
c(10);
c.reset();
c.interval = 5.0;
类
- 类init
class Student{
fullName: string;
//constructor = init方法, new = alloc 方法
constructor(public firstName, public middleInitial, public lastName){
this.fullName = firstName + " " + middleInitial + " " + lastName;
}
greet() {
return "Hello, " + this.fullName;
}
}
interface Person {
firstName: string;
lastName: string;
}
function greeter(person: Person) {
return "Hello" + " " + person.firstName + " " + person.lastName;
}
var user = new Student("Never", "Yaphets", "Y-II");
document.body.innerHTML = greeter(user);
- 继承 - extends 只能单继承
- 类 - 公共, 私有与受保护的修饰符
- 默认为public
- private = 只能在类的内部使用(子类都不行)
- protected = 能在类和子类中使用
- readonly
- static 静态属性,存在于类本身上面而不是类的实例上面
- abstract 抽象类 - 不会被实例化
- 存取器
let passcode = "secret passcode";
class Employee {
private _fullName: string;
get fullName(): string {
return this._fullName;
}
set fullName(newName: string) {
if (passcode && passcode == "secret passcode") {
this._fullName = newName;
}
else {
console.log("Error: Unauthorized update of employee!");
}
}
}
let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
alert(employee.fullName);
}
TS2.7
- 严格性标记: --strictPropertyInitialization , 使用这个标记会确保类的每个实例属性都会在够造函数中被初始化
- 显示赋值断言, 用来告诉TS一个属性会被明确地赋值
let x!: number[];
initialize();
x.push(4);
function initialize() {
x = [0, 1, 2, 3];
}
假设我们没有在 x后面加上感叹号,那么TypeScript会报告 x从未被初始化过。 它在延迟初始化或重新初始化的场景下很方便使用。
基础类型
- 布尔值 boolean
let isDone: boolean = false;
- 数字:
let decLiteral: number = 6;
- 字符串:
let name: string = "bob";
- 数组
let list: number[] = [1, 2, 3];
let list: Array<number> = [1, 2, 3];
- 元组Tuple
// Declare a tuple type
let x: [string, number];
// Initialize it
x = ['hello', 10]; // OK
// Initialize it incorrectly
x = [10, 'hello']; // Error
- 枚举
enum Color {Red, Green, Blue};
let c: Color = Color.Green;
- 泛型 T = id
和any类型的区别是: 虽然使用any类型后这个函数已经能接收任何类型的arg参数,但是却丢失了一些信息:传入的类型与返回的类型应该是相同的。 如果我们传入一个数字,我们只知道任何类型的值都有可能被返回。
因此,我们需要一种方法使返回值的类型与传入参数的类型是相同的。 这里,我们使用了 类型变量,它是一种特殊的变量,只用于表示类型而不是值。
function identity<T>(arg: T): T {
return arg;
}
我们给identity添加了类型变量T。 T帮助我们捕获用户传入的类型(比如:number),之后我们就可以使用这个类型。 之后我们再次使用了 T当做返回值类型。现在我们可以知道参数类型与返回值类型是相同的了。 这允许我们跟踪函数里使用的类型的信息。
我们把这个版本的identity函数叫做泛型,因为它可以适用于多个类型。 不同于使用 any,它不会丢失信息,像第一个例子那像保持准确性,传入数值类型并返回数值类型。
使用 let output = identity("myString"); // type of output will be 'string'
- 任意值 any == id
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean
- void null undefined
- 默认情况null和undefined是所有类型的子类型
- Never - 永远不存在的值的类型
类型断言 = 类型转化
- 尖括号语法
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;
解构
- 解构数组
let input = [1, 2];
let [first, second] = input;
console.log(first); // outputs 1
console.log(second); // outputs 2
这创建了2个命名变量 first 和 second。 相当于使用了索引,但更为方便
- 解构对象
let o = {
a: "foo",
b: 12,
c: "bar"
}
let {a, b} = o;
- 默认值, 默认值可以让你在属性为undefined时使用缺省值
function keepWholeObject(wholeObject: {a: string, b?: number}) {
let {a, b = 1001} = wholeObject;
}
现在,即使 b 为 undefined , keepWholeObject 函数的变量 wholeObject 的属性 a 和 b 都会有值。
函数
function add(x: number, y: number): number {
return x + y;
}
let myAdd = function(x: number, y: number): number { return x+y; };
如果函数没有返回值, 也必须制定返回值类型为void, 而不能留空
函数的可选参数 --- ?
function buildName(firstName: string, lastName?: string) {
if (lastName)
return firstName + " " + lastName;
else
return firstName;
}
let result1 = buildName("Bob"); // works correctly now
let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
let result3 = buildName("Bob", "Adams"); // ah, just right
注意: 可选参数必须放在必须参数后面
函数的默认参数
function buildName(firstName = "Will", lastName: 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"); // okay and returns "Bob Adams"
let result4 = buildName(undefined, "Adams"); // okay and returns "Will Adams"
函数的剩余参数
function buildName(firstName: string, ...restOfName: string[]) {
return firstName + " " + restOfName.join(" ");
}
let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");