typescript对象类型篇 - 索引签名

545 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 2 天,点击查看活动详情

索引签名

当我们并不清楚除具体的属性名和个数,但想确定属性类型的时候,可以通过索引签名来定义,如

type IndexS = {
 [key: string]: string
}

上面代码定义了IndexS对象类型,指定属性名和属性值都为string类型,其中key可以为任意值。假如指定属性名为number类型,则可以理解为表示一个字符串数组,如

type IndexS2 = {
   [key: number]: string
}

let stringArr:IndexS2 = ['1','2','3']

索引签名属性取值类型

索引签名的属性名可以指定为string,number,symbol,"template string patterns"(这个类型我不是太理解)以及上面几种类型的组合类型

索引签名注意事项

  1. ts允许同时定义多种索引签名类型,但应注意,同时指定索引签名属性为number和string类型时,number对应的属性值类型应是string对应的属性的子类型。如
interface Animal {
    name: string
}

interface Dog extends Animal {
    breed: string
}
type IndexSignature = {
    [key:string]: Animal;
    [key: number]: Dog    
}

let is:IndexSignature = {
    "str": {
        name: "name"
    },
    0: {
        name: "name",
        breed: "breed"
    } as Dog
}

上面我们创建了IndexSignature类型,指定其属性名可以为string或number类型,但指定为number类型的属性名对应的属性值类型(Dog)必须是string类型对应的属性值(Animal)的子类。原因是js会自动将number类型的属性名转化成字符串类型。下面附上ts官方解释:

It is possible to support both types of indexers, but the type returned from a numeric indexer must be a subtype of the type returned from the string indexer. This is because when indexing with a number, JavaScript will actually convert that to a string before indexing into an object. That means that indexing with 100 (a number) is the same thing as indexing with "100" (a string), so the two need to be consistent.

  1. “索引签名”要求所有属性对应的属性值类型要满足“索引签名”定义的属性值类型,如

type IndexSignature = {
    [key: string]: string;
    age: number // Property 'age' of type 'number' is not assignable to 'string' index type 'string'
}

上面IndexSignature限制了属性值为字符串类型,则不允许定义number类型得age属性。若想同时定义属性值为number或string类型,可使用组合类型,如


type IndexSignature = {
    [key: string]: string | number;
    age: number  
}