2017-09-04 278 views
2

我正在使用启用了严格空值检查的Typescript。当我尝试编译下面的代码时,我得到错误“type'null'不能用作索引类型。”类型'null'不能用作索引类型

function buildInverseMap(source: Array<string | null>) { 
    var inverseMap: { [key: string]: number } = {}; 
    for (let i = 0; i < source.length; i++) { 
     inverseMap[source[i]] = i; 
    } 
} 

很明显,inverseMap不能有null作为关键字,因为类型约束不允许它。但是,如果我改变inverseMap的类型是:

var inverseMap: { [key: string | null]: number } = {}; 

我得到的错误“索引签名的参数类型必须是‘串’或‘号’。”这很奇怪,因为在JavaScript中使用null作为索引是合法的。例如,如果运行在浏览器中下面的代码:

var map = {}; 
map[null] = 3; 
map[null]; 

输出为3.是否有办法做到这一点的打字稿或者是打字稿不够聪明做到这一点?

+0

我有点惊讶,你可以在JavaScript中设置一个'空'索引!我检查,它的工作。本来打赌它会给我带来某种错误。 也许typescript是逻辑,只是不允许 – sheplu

+1

我认为这可能是我的错误。最初他们将索引参数限制为字符串,我猜测他们添加了严格的空检查时没有改变验证。 –

回答

3

在JavaScript对象键,无论你相信与否,总是strings(好吧,或Symbols)。 (另请参阅this answer)。当你传递一个非字符串值作为关键字时,它首先被强制转换为一个字符串。所以,在

var map = {}; 
map[null] = 3; 
map[null]; 

你实际上是设置map["null"]。注意:

console.log(map["null"]===map[null]); // true 

所以,打字稿他们积极决定only allow the string or number type as index signatures。可能是因为大多数时候,任何人试图使用诸如null之类的东西来索引对象都表示有错误。

在你的情况,你可以做这样的事情:

function buildInverseMap(source: Array<string | null>) : {[key: string] : number} { 
    var inverseMap: { [key: string]: number } = {}; 
    for (let i = 0; i < source.length; i++) { 
     inverseMap[String(source[i])] = i; // coerce to string yourself 
    } 
    return inverseMap; 
} 

注意我们如何强制source[i]string自己,这让打字稿高兴。如果你还记得包裹键与String()每当你可能会与空使用它,它应该为你工作:

const inverseMap = buildInverseMap(['a', 'b', null, 'c']); 
const aIndex = inverseMap['a']; 
const nullIndex = inverseMap[String(null)]; 

希望帮助!祝你好运。

2

map[null] = 3;具有完全一样做map['null'] = 3; 因此你可能只用'null'在打字稿是否适合你同样的效果。

2

JavaScript就不允许nullundefined作为对象键,你都没有意识到这一点,但你让他们的字符串值,所以:

let a = {}; 
a[null] = "i am null"; 
a[undefined] = "i am undefined"; 
console.log(a[null] === a["null"]); // true; 
console.log(a[undefined] === a["undefined"]); // true; 

在打字稿,他们决定索引只能是stringnumber(尽管在使用数字作为键时也会转换为字符串),这就是为什么你有这些错误。

在你的情况下,我只是这样做:

inverseMap[source[i] || "null"] = i;