Learning TypescriptTypeScript

Typescript 深入讲解可索引类型 Indexable T

2020-03-20  本文已影响0人  张毅_f72c

1. 准备工作

npm init -y
npm install ts-node typescript

2. Typescript可索引类型

Typescript同时支持number和string类型的索引类型。

2.1 number可索引类型

2.1.1 Sample Code

interface NumIndexType {
    [numIdx: number]: any;
}

let myVar: NumIndexType;

myVar = ["elem1", "eleme2", "elem3"];

console.log('-------> type: ' + (typeof myVar));
console.log('-------> instanceof Array?: ' + (myVar instanceof Array));

console.log('-------> toString: ' + myVar.toString());

console.log('-------> iterate: ');

for (let v  in myVar) {
    console.log(v);
}

2.1.2 Result

编译执行: npx ts-node test.ts
执行结果:

-------> type: object
-------> instanceof Array?: true
-------> toString: elem1,eleme2,elem3
-------> iterate:
0
1
2

2.1.3 结果分析

2.2 string可索引类型

2.2.1 Sample Code

interface NumIndexType {
    [numIdx: number]: any;
    [strIdx: string]: any;
}

let myVar: NumIndexType;

myVar = ["elem1", "eleme2", "elem3"];

myVar["strIdx0"] = "strIdx0:0";
myVar["strIdx1"] = "strIdx1:1";

console.log('-------> type: ' + (typeof myVar));
console.log('-------> instanceof Array?: ' + (myVar instanceof Array));

console.log('-------> toString: ' + myVar.toString());

console.log('-------> iterate: ');

for (let v  in myVar) {
    console.log(v);
}

console.log('array length: ' + myVar.length);


console.log('--------> 我是分割线 -------->');

console.log("myVar['strIdx0']: " + myVar["strIdx0"]);
console.log("myVar['strIdx1']: " + myVar["strIdx1"]);
console.log('toStirng(): ' + myVar.toString());

console.log(myVar.strIdx0);

console.log('array length: ' + myVar.length);

2.2.2 Result

-------> type: object
-------> instanceof Array?: true
-------> toString: elem1,eleme2,elem3
-------> iterate:
0
1
2
strIdx0
strIdx1
array length: 3
--------> 我是分割线 -------->
myVar['strIdx0']: strIdx0:0
myVar['strIdx1']: strIdx1:1
toStirng(): elem1,eleme2,elem3
strIdx0:0
array length: 3

2.2.3 结果分析

2.2.4 number索引类型、其他属性如何与string索引类型共存

2.2.4.1 如果同时有number和string索引类型,那么number索引类型的返回值类型必须是string索引类型的子类

如下代码(摘自官方文档,但是不妨碍老张解释):

class Animal {
    name: string;
}

class Dog extends Animal {
    breed: string;
}

interface NotOkay {
    [x: number]: Animal;
    [x: string]: Dog;
}

解释:

⨯ Unable to compile TypeScript:
Animal.ts:10:2 - error TS2413: Numeric index type 'Animal' is not assignable to string index type 'Dog'.

10  [x: number]: Animal;
    ~~~~~~~~~~~~~~~~~~~~

2.2.4.2 在一个interface中,只定义了string类型索引,对其他的属性有什么约束?

interface NumberOrStringDictionary {
    [index: string]: number ;
}

上面的代码片段,定义类一个string类型索引,返回值类型是number,那么其实就是限定了这个类的其他属性也是number或其子类型(这个其实就是设计模式的里式替换原则,父类可以在的地方,就可以用子类代替)。

interface NumberOrStringDictionary {
    [index: string]: number;
    length: number;
    name: string;
}

按理论,所有非索引类型属性,类型必须是number或number的子类。显然,name属性是错误的。编译会有如下错误:

Animal.ts:4:5 - error TS2411: Property 'name' of type 'string' is not assignable to string index type 'number'.

4     name: string;
      ~~~~
interface NumberOrStringDictionary {
    [index: string]: number| string;
    length: number;
    name: string;
}

再次将不会出现错误。

3. Summary

上一篇下一篇

猜你喜欢

热点阅读