当你写
const myArray = [
{ name: "Alice", age: 15 },
{ name: "Bob", age: 23 },
{ name: "Eve", age: 38 },
];
TypScript推断其为类型
// const myArray: { name: string; age: number; }[]
这只是一种简写的写作方式
// const myArray: Array<{ name: string; age: number; }>
所以myArray
有array type.如果你看the TypeScript type definition for Array<T>
,它有一个数字index signature:
interface Array<T> {
// ⋮
[n: number]: T;
}
这意味着TypScript将允许您使用数字键对其进行索引.特别是,indexed access Array<T>[number]
只会返回T
.
您似乎在问为什么它没有抱怨,因为数组的contents并不是每个数字索引都有值.答案是因为类型不跟踪内容.
此外,形式{[key: K]: V}
的索引签名并不意味着"该对象中存在类型K
的每个键并且具有类型V
的值". 相反,它意味着"如果该对象中存在类型K
的键,那么其值是类型V
."因此,(typeof myArray)[number]
始终是{ name: string; age: number; }
,尽管如果您执行任意索引操作,您可能会在实践中看到undefined
. 如果您希望将undefined
视为索引操作的可能value,则可以打开--noUncheckedIndexedAccess
:
const person = myArray[4];
// if --noUncheckedIndexedAccess is off
// const person: { name: string; age: number; }
// if --noUncheckedIndexedAccess is on
// const person: { name: string; age: number; } | undefined
但索引访问类型将保持不变.
有tuple types个限制数组在特定索引处包含特定值类型,并且其长度是预先已知的.如果您在初始化数组文字上使用const
assertion,您将获得更接近您可能正在寻找的类型的信息:
const myArrayConst = [
{ name: "Alice", age: 15 },
{ name: "Bob", age: 23 },
{ name: "Eve", age: 38 },
] as const;
/* const myArrayConst: readonly [{
readonly name: "Alice";
readonly age: 15;
}, {
readonly name: "Bob";
readonly age: 23;
}, {
readonly name: "Eve";
readonly age: 38;
}] */
现在TypScript知道length
是3
,并且如果它看到您使用已知越界的字面数字进行索引,就会抱怨:
let personConst: Person;
personConst = myArrayConst[0]; // okay
personConst = myArrayConst[4]; // error! no element at index '4'
// error! Type 'undefined' is not assignable
但同样,这不会改变数字索引签名处发生的情况:
type PersonConst = (typeof myArrayConst)[number];
/* type PersonConst = {
readonly name: "Alice";
readonly age: 15;
} | {
readonly name: "Bob";
readonly age: 23;
} | {
readonly name: "Eve";
readonly age: 38;
} */
myArrayConst[Math.random()] // okay, number is still a valid index
仍然允许索引,并且索引访问仍然为您提供不含undefined
的元素类型.
Playground link to code