本文列举了 ts 的几种不常见用法,分别是:
- 函数重载
- 接口继承
- 类的内容
- 属性关键字
- 存储器
getter
setter
extends
vs implements
- 泛型类
函数重载 ( Function Overloading )
这种其实可以用可选参数 + 或者类型替代,但如果把所有函数返回类型都列出,会清晰点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| interface Circle { radius: number; }
interface Rectangle { width: number; height: number; }
function calculateArea(shape: Circle): number; function calculateArea(shape: Rectangle): number;
function calculateArea(shape: any) { if ((<Circle>shape).radius !== undefined) { return Math.PI * (<Circle>shape).radius ** 2; } else if ( (<Rectangle>shape).width !== undefined && (<Rectangle>shape).height !== undefined ) { return (<Rectangle>shape).width * (<Rectangle>shape).height; } else { throw new Error('Unsupported shape type'); } }
const circleArea = calculateArea({ radius: 5 }); console.log(circleArea); const rectangleArea = calculateArea({ width: 10, height: 5 }); console.log(rectangleArea);
|
接口继承 ( Interface Extend )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| interface Parent1 { p1: string; p2: number; }
interface Parent2 { p3: boolean; }
interface Child extends Parent1, Parent2 { p4: string | number; }
const o: Child = { p1: "", p2: 0, p3: false, p4: "", };
|
类 ( Class )
定义属性
在ts里,所有属性需要在 constructor
之前规定其属性,如以下示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class Article { title: string; content: string; a?: string; b = '';
constructor(title: string, content: string) { this.title = title; this.content = content; } }
const a = new Article('题目', '内容');
|
public
,private
, protected
, static
, readonly
关键字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class Artical { public title?: string; private content?: string; protected innerData?: string; static author: string = 'Jone'; readonly version?: string;
protected static readonly c: string = '' constructor(title: string, content: string) { this.title = title; this.content = content; } }
|
getter
setter
和私有值
- 私有属性,不想被外部访问,命名一般用下划线区分
- 一般一个私有值,对应一个
getter
, setter
存储器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class User { private _password: string = '';
get password(): string { return '*' }
set password(newPassword: string) { this._password = newPassword } }
const u = new User();
console.log(u.password);
|
抽象类 abstract
vs 实现接口implements interface
abstract
用于给子类继承用,不单独做实例化
implements
和 abstract
的区别是,implements
可以实现多个接口 interface
, 而 extends
只能继承一个抽象类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| abstract class Animal { abstract name: string; abstract voice(): void; }
class Cat extends Animal { name: string = 'Cat'; voice(): void { console.log('miao') } }
const c1 = new Cat();
interface AnimalName { name: string; } interface AnimalVoice { voice(): void; }
class Dog implements AnimalName, AnimalVoice { name: string = 'Dog'; voice() { console.log('wang') } }
const d1 = new Dog();
|
当然,他们还能同时使用,但 extends
必须用在 implements
之前:
1 2 3 4 5 6
| class Dog extends Animal implements AnimalName, AnimalVoice { name: string = 'Dog'; voice() { console.log('wang') } }
|
泛型类
泛型除了应用在函数,还可以放在类里应用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class TestGenric<T> { value: T; constructor(value: T) { this.value = value; }
processValue (input: T): T { return input } }
const s = new TestGenric<string>('string'); s.processValue('string');
const n = new TestGenric<number>(123); n.processValue(123);
|