工具: PlayGround
接口用来定义对象的结构和类型,描述对象应该具有哪些属性和方法。
它仅用于声明,而不是实现; 这对于编写可重用的代码非常有用。它可用于:
关键字是interface
, 注意:它只是作为TypeScript
的一部分,并不会转换为JavaScript
interface data {
[index:number]: number,
}
// 类型一致,没有问题
let numList_1: data = [1, 2, 3];
// Type 'string' is not assignable to type 'number'
let numList_2: data = [1, "", 3];
// 方式1
interface Data_1 {
name: string,
age: number,
}
let data_1: Data_1 = {
name: "hello",
age: 20,
}
console.log(data_1);
// 方式2
interface Data_2 {
name: string;
age: number;
// 可选属性, 表示可以选择不赋值
sex?: number;
// 只读属性,表示一旦赋值后不可修改
readonly id:number | string;
}
let data_2: Data_2 = {
name: "hello",
age: 20,
id : "0001",
}
data_2.age = 10;
// Error: Cannot assign to 'id' because it is a read-only property
data_2.id = 10;
interface Person {
name: string;
age: number;
greet: () => void;
}
// 通过implements实现接口
class Student implements Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, my name is ${this.name}`);
}
}
let student = new Student("ok", 20);
student.greet(); // "Hello, my name is ok"
typeScript中类的使用,主要通过class
来创建类对象,通过new
来实例化类对象, 支持特性:
instanceof
检测对象类型
访问权限public
、protected
和private
函数重载
继承或重写
静态成员和方法
基本的使用:
class Demo {
private _name: string = "";
private _age: number = 0;
// 构造函数
constructor(name:string) {
this._name = name;
}
public log() {
console.log(`Demo 的名字为${this._name}`);
}
}
let demo = new Demo("demo");
console.log(typeof(demo)); // "object"
console.log(demo instanceof Demo); // true
类的函数重载的编写方式,不要直接实现:
class Demo {
private _name: string = "";
private _age: number = 0;
// 构造函数
constructor(name:string) {
//
}
// Error: Multiple constructor implementations are not allowed
// 原因在于如果实现,编译器创建对象不知道调用哪个构造函数
constructor(name: string, age:number) {
//
}
}
可以通过采用声明和可选参数的方式来实现:
// 实例1
class Demo {
private _name: string = "";
private _age: number = 0;
// 构造函数
constructor(name:string);
constructor(name: string, age:number);
constructor(name: string, age?:number) {
this._name = name;
if (age) {
this._age = age;
}
}
}
// 实例2:
class Calculator {
add(a: number, b: number): number;
add(a: string, b: string): string;
add(a: any, b: any): any {
if (typeof a === 'number' && typeof b === 'number') {
return a + b;
} else if (typeof a === 'string' && typeof b === 'string') {
return a.concat(b);
} else {
throw new Error('Invalid arguments');
}
}
}
const calculator = new Calculator();
console.log(calculator.add(1, 2)); // 3
console.log(calculator.add('Hello', ' World')); // Hello World
继承的话,使用extends
, 如果对基类中的方法重新编写,就是重写
// 定义接口,简单的实例可以忽略;增加的话,有助于理解代码和重写代码相关
interface Animal {
sound(): void;
}
// 实现接口
class Cat implements Animal {
private _breed: string;
private _name: string = "Cat";
constructor(breed: string) {
this._breed = breed;
}
// 通过get和set的方式设置对象变量属性
get Name():string {
return this._name;
}
set Name(name: string) {
this._name = name;
}
sound(): void {
console.log("猫");
}
}
// 继承
class DomesticCat extends Cat {
public log() {
console.log("this is DomesticCat");
}
}
// 重写
class WildCat extends DomesticCat {
sound(): void {
console.log("野猫叫声");
}
}
const domesticCat = new DomesticCat("domesticCat");
domesticCat.Name = "短毛猫"
console.log(`cat Name: ${domesticCat.Name}`); //"cat Name: 短毛猫"
domesticCat.sound(); // 猫
//
const wildCat = new WildCat("豹猫");
wildCat.sound(); // 野猫叫声
注意:
public
、protected
和private
,则默认为public
_
表示私有extends
后面添加类接口即可implements
和extends
,前者主要用于对interface声明的方法等进行实现, 而后者主要应用于已经实现后的方法进行继承或重写。静态变量或方法在类中声明后,可以不通过new
对象直接赋值或使用,但赋值后不可在改变。
class Demo {
static value: number;
static getValue() {
console.log(`static value: ${Demo.value}`);
}
}
Demo.value = 10;
Demo.getValue(); //"static value: 10"
它常用于编写单例模式,注意: 构造函数设置为私有,以保证对象的唯一性
class Singleton {
private static instance: Singleton;
private constructor() {
// 私有化构造函数,防止外部实例化
}
public static getInstance(): Singleton {
if (!Singleton.instance) {
Singleton.instance = new Singleton();
}
return Singleton.instance;
}
public greet(): void {
console.log("Hello");
}
}
// 创建单例实例
const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // true
instance1.greet(); // "Hello"
instance2.greet(); // "Hello"
作为常量使用,在类中使用注意:
const
一定要记得初始化,不能在构造函数或其他函数进行初始化readonly
只读属性class MyClass {
readonly PI: number = 3.14;
readonly config: { name: string, age: number } = { name: "John", age: 25 };
constructor() {
// this.PI = 3.14159; // 错误,无法对只读属性进行重新赋值
// this.config = { name: "Alice", age: 30 }; // 错误,无法对只读属性进行重新赋值
this.config.name = "Alice"; // 正确,可以修改对象字面量属性的值
this.config.age = 30; // 正确,可以修改对象字面量属性的值
}
printInfo(): void {
console.log(`PI: ${this.PI}`);
console.log(`Name: ${this.config.name}, Age: ${this.config.age}`);
}
}
const myObj = new MyClass();
myObj.printInfo();
// "PI: 3.14"
// "Name: Alice, Age: 30"