如何用任意键声明一个类型化的对象?

mpe*_*pen 8 typescript

.d.ts文件中,如何将对象定义为具有字符串键和T值?

例如

declare var Game: {
    creeps: Object<string, Creep>; // not sure what syntax to use here
};

declare class Creep {
   // definition...
}
Run Code Online (Sandbox Code Playgroud)

Game.creeps是一个object,但我不知道它将具有什么属性/键(它们是在运行时定义的 - 我像字典一样使用它),但是,我知道它的所有值都是Creeps.

我的IDE说"对象不是通用的"所以我猜这种语法不太正确.

bas*_*rat 16

使用索引签名:

declare var Game: {
    creeps: {[key:string]: Creep}
};
Run Code Online (Sandbox Code Playgroud)

  • 您需要以字典的形式访问它,即`creeps['key']` 而不是`creeps.key`。如果您知道密钥名称,那么您应该将其添加为标准道具而不是使用索引签名 (2认同)
  • 啊哈!我没想到那些行为会有所不同。再次感谢 :-) (2认同)

ock*_*888 11

basrat 的答案仍然可以正常工作,但是在 Typescript 2.1 或更高版本中,有一种类型看起来更类似于您最初认为可能有效的类型:

declare var Game: {
    creeps: Record<string, Creep>
};
Run Code Online (Sandbox Code Playgroud)

没有真正的区别,尽管我要补充一点,Typescript 假设对于任何K值 a 都Record<K, V>可以产生相应的V值。例如:

type Creep = {
    id: number;
}

function printIt(c: Creep) {
    console.log(c.id);
}

let game: Record<string, Creep> = {"test": {id: 0}};
printIt(thing["quest"]);
Run Code Online (Sandbox Code Playgroud)

会编译 - 即使使用strictNullChecks- 尽管它肯定会导致运行时错误。因此,您需要自己检查索引访问,和/或--noUncheckedIndexedAccess按照 @mpen 建议使用该标志。

  • TS 4.1 中有一个新标志,如果您想收到警告,它将把所有索引签名视为可选。`--noUncheckedIndexedAccess` (2认同)