接口
1 2 3 4 5 6 7 8
| interface labelValue { label : string } function printLabel2(obj: labelValue) { console.log(obj.label) }
printLabel2(myObj)
|
duck-typing特性(鸭子类型)
- 检验两个比较的对象是否具有相同的属性及类型,b是否包含a
- 如person与Person的比较,虽然person的属性数量大于Person,但是person具有Person的所有属性且类型相同,所以,检验过程成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| interface Person { name: string age: number sex: number }
const person = { name: 'schnuffel', age: 18, sex: 1, msg: '1231312312' }
const testFunc = (param: Person) => { return param }
testFunc(person)
|
可选、只读属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| interface SquareConfig { color?: string readonly y: number } function createSquare(config: SquareConfig): { color: string; area: number } { let newSquare = {color: "white", area: 100} if (config.color) { newSquare.color = config.color } return newSquare } let mySquare = createSquare({color: "black"}) let p1: SquareConfig = { y: 20 }
|
只读数组ReadonlyArray:创建后不能被修改
1 2 3 4
| let a: number[] = [1, 2, 3, 4] let ro: ReadonlyArray<number> = a
a = ro as number[]
|
额外的属性检查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| interface SquareConfig { color?: string width?: string } function createSquare(config:SquareConfig): {color: string; area: number}{} let mySquare = createSquare({ colour: "red", width: 100 })
解决方法1:类型断言: let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig)
解决方法2:字符串索引签名(最佳): interface SquareConfig { color?: string; width?: number; [propName: string]: any; }
解决方法3: 将这个对象赋值给另一个变量 let squareOptions = { colour: "red", width: 100 } let mySquare = createSquare(squareOptions)
|
函数类型
1 2 3 4 5 6 7 8
| interface SearchFunc { (source: string, subString: string): boolean }
mySearch:SearchFunc = function(src: string, sub: string): boolean { let result = src.search(sub); return result > -1; }
|
可索引的类型
- ts支持两种索引签名:字符串和数字。可同时使用,但是数字索引的返回值必须是字符串索引返回值类型的子类型
- 可以设置为只读: readonly [index: number]: string
1 2 3
| interface StringArray { [index: number]: string }
|
类类型
实现接口 implements
- 接口描述了类的公共部分。它不会帮你检查类是否具有某些私有成员。
1 2 3 4 5 6 7 8 9 10 11 12
| interface ClockInterface { currentTime: Date setTime(d: Date) }
class Clock implements ClockInterface { currentTime: Date; setTime(d: Date) { this.currentTime = d } constructor(h: number, m: number) {} }
|
继承接口 extends
- 一个接口可以继承多个接口,继承多个接口的接口叫做合成接口
1 2 3 4 5
| interface Square extends Shape, PenStroke { sideLength: number }
let square = <Square>{}
|
混合接口:js使用第三方库时用
1 2 3 4 5 6 7 8 9 10 11 12
| 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 }
|
接口继承类型
- 接口继承类,可继承类的私有属性和protected,但只能被这个类和它的子类实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Control { private state: any } interface SelectableControl extends Control { select(): void }
class Button extends Control implements SelectableControl { select() { } }
class TextBox extends Control { select() { } }
|
类
通过extends的类叫做派生类或子类,而父类叫做基类或超类
修饰符
public:默认,公共属性
private:私有属性,不能在声明它的类的外部访问。
- private和protected在比较类型时,只有两个类型都有同样的修饰符,并且该修饰符来自同一基类时,才认为这两个类型是兼容的。
1 2 3 4 5 6 7 8 9 10
| class Animal { private name: string; constructor(theName: string) { this.name = theName } }
class Rhino extends Animal { constructor() { super("Rhino") } } let animal = new Animal("Goat") let rhino = new Rhino()
|
protected:保护属性
- 不能在声明它的类的外部访问,但派生类中仍然可以访问
- 构造函数也可以被标记成 protected。这意味着这个类不能在包含它的类外被实例化,但是能被继承
readonly:只读修饰符,必须在声明时或构造函数里被初始化。
static: 静态属性,只有当前类才有的属性
abstract:抽象类
- 做为其它派生类的基类使用。 它们一般不会直接被实例化
- 定义的方法必须在派生类中实现,派生类的构造函数必须调用super()
1 2 3
| let department: Department department = new 子类名() department.printName()
|
存取器:get和set成对出现
- get 变量名()
- set 变量名()
1 2 3 4 5 6
| getToken(): Itoken { return Initoken }, setToken( tokenData: Itoken ): Itoken { return ( Initoken = { ...Initoken, ...tokenData } ) }
|
高级技巧 — 构造函数
- 类定义会创建两个东西:类的实例类型和一个构造函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Greeter { static standardGreeting = "Hello,there" greeting: string constructor(message: string) { this.greeting = message }, greet() { return "Hello, " + this.greeting } }
let greeter: Greeter greeter = new Greeter("world")
let greeterMaker: typeof Greeter = Greeter greeterMaker.standardGreeting = "Hey there!"
|
把类当做接口使用:类可以创建出类型,所以在允许使用接口的地方可以使用类
1 2 3 4 5 6 7 8
| class Point { x: number y: number }
interface Point3d extends Point { z: number }
|
es5 vs es6 的类区别
- es6:class类必须new调用,不能直接执行
- 不存在变量提升
- 无法遍历它实例原型链上的属性和方法
- es5:类和普通函数无区别,可以执行