当您使用初始值设定项声明变量时,类型脚本必须从其初始值设定项中 Select 该变量的类型为infer.并且有许多可能的类型与任何给定的初始值设定项兼容.例如,给定:
const json = { 1: ["", 1], 2: ["", 2] };
以下类型将全部兼容:
const json1: MyRecord = { 1: ["", 1], 2: ["", 2] };
const json2: unknown = { 1: ["", 1], 2: ["", 2] };
const json3: Record<number, any> = { 1: ["", 1], 2: ["", 2] };
const json4: { 1: any[], 2: ["", 2] } = { 1: ["", 1], 2: ["", 2] };
const json5: MyRecord | string = { 1: ["", 1], 2: ["", 2] };
编译器必须挑选一个.多么?它使用了heuristics个适合广泛用途的产品.在这种情况下,结果是:
/* const json: {
1: (string | number)[];
2: (string | number)[];
} */
您可以看到,数组文字["", 1]
被推断为具有类型(string | number)[]
,这是一个任意长度的无序可变数组,其中每个元素可以是一个字符串或一个数字.如果您想像修改json[1][2] = 3
那样修改数组,您会很满意的.
但不幸的是,您想要later使用json
作为MyRecord
.由于json
的类型不可赋给它,所以它失败了.在推断变量的类型时,编译器不会考虑将来的使用.(试想一下,这样做的编译器执行起来会有多糟糕.)任何比{1: (string | number)[]; 2: (string | number)[]}
更具体的信息(编译器将初始化式设置为json
)已经被丢弃了.
另一方面,当你写下这句话时:
const success: MyRecord = { 1: ["", 1], 2: ["", 2] };
(与上面的json1
相同)它起作用了.这是因为编译器不再需要infer变量的类型.它只需根据类型判断初始值设定项.因此,它对照MyRecord
判断初始值设定项,并发现它满足定义.换句话说,这是因为它使用变量类型来分析初始值设定项,而不是使用初始值设定项来分析变量.
Playground lik to code个