如果您尝试为不存在的属性编制索引,您甚至会看到错误:
1. type Person = { age: number; name: string; alive: boolean }; 2. 3. // 编译报错,类型“Person”上不存在属性“alve”。 4. type I1 = Person["alve"];
用于获取数组元素的类型,我们可以将其方便地捕获数组对应的元素类型:number typeof
1. const MyArray = [ 2. { name: "Alice", age: 15 }, 3. { name: "Bob", age: 23 }, 4. { name: "Eve", age: 38 }, 5. ]; 6. 7. // type Person = { 8. // name: string; 9. // age: number; 10. // } 11. type Person = typeof MyArray[number]; 12. 13. // type Age = numbers 14. type Age = typeof MyArray[number]["age"]; 15. // Or 16. type Age2 = Person["age"];
只能在索引时使用类型,这意味着不能使用 进行变量引用:const
1. const key = "age"; 2. //报错,类型“key”不能作为索引类型使用。 3. type Age = Person[key]; 4. // 可以 5. type Age1 = Person['age'];
用类型别名是可以的。
1. type key = "age"; 2. // 可以 type Age = number 3. type Age = Person[key];
7、类类型
C#或Java里接口的基本作用一样,TypeScript也能够用它来明确的强制一个类去符合某种契约。也就是面对对象编程中类的继承概念,定义一个接口,由类去实现这个接口。
1. interface animal { 2. birthday: Date 3. getInfo(): string 4. } 5. 6. class Cat implements animal { 7. birthday: Date; 8. name: string; 9. getInfo() :string { 10. return this.name + ", " + this.birthday; 11. } 12. constructor(name: string, birthday: Date) { 13. this.name = name; 14. this.birthday = birthday; 15. } 16. } 17. 18. let c1 = new Cat('叮当猫', new Date('2023-05-09')); 19. console.log(c1.getInfo()); 20. // 叮当猫, Tue May 09 2023 08:00:00 GMT+0800 (China Standard Time)
7.1 类静态部分和实例部分
在操作类和接口的时候,当你用构造器签名去定义一个接口并试图定义一个类去实现这个接口时会得到一个错误:
1. interface Animal { 2. birthday: Date 3. new(name: string, birthday: Date) 4. } 5. // 编译错误,类型“Cat”提供的内容与签名“new (name: string, birthday: Date): any”不匹配。 6. class Cat implements Animal { 7. birthday: Date; 8. name: string; 9. getInfo() :string { 10. return this.name + ", " + this.birthday; 11. } 12. constructor(name: string, birthday: Date) { 13. this.name = name; 14. this.birthday = birthday; 15. } 16. }
所以,在类的静态部分我们做一些改变,我们再增加一个接口AnimalInter,然后把原接口构造器添加一个返回值为AnimalInter接口,新建一个函数,函数的返回类型为AnimalInter接口,而函数的第一个参数进行实例化,如下图所示:
1. interface Animal { 2. new(name: string, birthday: Date): AnimalInter 3. } 4. 5. interface AnimalInter { 6. getInfo() : string 7. } 8. 9. function CreateFunc(first:Animal, name: string, birthday: Date ):AnimalInter { 10. return new first(name, birthday) 11. } 12. 13. class Cat{ 14. birthday: Date; 15. name: string; 16. getInfo() { 17. return this.name + ", " + this.birthday; 18. } 19. constructor(name: string, birthday: Date) { 20. this.name = name; 21. this.birthday = birthday; 22. } 23. } 24. 25. let result = CreateFunc(Cat, '张三', new Date('2023-02-09')) 26. console.log('result: ', result.getInfo());
这样在示例化这个Cat类的时候,检查是否和Animal接口构造函数定义的一致。
8、继承接口
接口的继承和类是一样的,是可以相互继承的,这样可以进行拆分多个接口,便于以后的可复用,重构起来也更方便,如下所示:
1. interface Animal { 2. name: string, 3. } 4. 5. interface AnimalInter extends Animal { 6. getInfo() : string 7. } 8. 9. class Cat implements AnimalInter{ 10. birthday: Date; 11. name: string; 12. getInfo() { 13. return this.name + ", " + this.birthday; 14. } 15. constructor(name: string, birthday: Date) { 16. this.name = name; 17. this.birthday = birthday; 18. } 19. } 20. 21. let result = new Cat('张三', new Date('2023-02-09')) 22. console.log('result: ', result.getInfo());
一个接口可以继承多个接口,创建出多个接口的合成接口。
1. interface Animal { 2. name: string, 3. } 4. interface AnimalSecond { 5. age: number, 6. } 7. 8. interface AnimalInter extends Animal, AnimalSecond { 9. getInfo() : string 10. } 11. 12. class Cat implements AnimalInter{ 13. birthday: Date; 14. name: string; 15. age: number; 16. getInfo() { 17. return this.name + ", " + this.birthday + ", age: "+this.age; 18. } 19. constructor(name: string, birthday: Date, age: number) { 20. this.name = name; 21. this.birthday = birthday; 22. this.age = age; 23. } 24. } 25. 26. let result = new Cat('张三', new Date('2023-02-09'), 20) 27. console.log('result: ', result.getInfo());
9、混合类型
混合类型,一个变量它的类型可能有多个,number | string| boolean 等,一个对象也可能是,以下就是一个对象,还可以是一个函数。
1. interface Animal { 2. (age: number): string; 3. name: string; 4. time: number; 5. } 6. 7. function getAnimal (): Animal { 8. let animal = function(age: number) {} as Animal 9. return animal; 10. } 11. let getResult = getAnimal(); 12. getResult(20); 13. getResult.time = 20; 14. // 报错,无法为“name”赋值,因为它是只读属性。函数的name,是可读的 15. getResult.name = '张三'; 16. console.log(getResult.time); 17. console.log(getResult.name );
10、接口继承类
接口继承类时,会继承类的成员,不包括对应的实现。接口可以继承类的私有成员,和受保护的成员,如果需要继承这个接口,只能由接口继承类的子类继承。在构造器函数中,子类的构造函数必须包含 "super" 的调用。
1. class AnimalClass { 2. private name: any; 3. } 4. 5. interface AnimalInterface extends AnimalClass{ 6. getName(): string; 7. } 8. 9. class Animal extends AnimalClass implements AnimalInterface{ 10. getName() { 11. return '123'; 12. }; 13. constructor() { 14. super(); 15. } 16. } 17. 18. // 类型 "Cat" 中缺少属性 "name",但类型 "AnimalInterface" 中需要该属性。 19. class Cat implements AnimalInterface { 20. getName() { 21. return '' 22. } 23. } 24. 25. let anima = new Animal()
Animal类继承AnimalClass类,在构造器中,必须调用super() 方法,子类进行初始化的时候,父类中有定义成员属性也需进行初始化操作,而AnimalInterface接口只能被AnimalClass类的子类所实现,因为本身接口就继承了AnimalClass类,而Cat在实现AnimalInterface接口时,必须包含接口从其他类中继承的所有属性,包括私有属性,Cat类不是AnimalInterface接口继承类的子类,所以就报错了,而父类私有属性不能通过子类实例化后的对象进行直接访问,也不会被继承。