Answers:
var stuff: { [key: string]: string; } = {};
stuff['a'] = ''; // ok
stuff['a'] = 4; // error
// ... or, if you're using this a lot and don't want to type so much ...
interface StringMap { [key: string]: string; }
var stuff2: StringMap = { };
// same as above
number
也可以作为索引类型
type Keys = 'Acceptable' | 'String' | 'Keys'
作为索引(键)类型?
interface AgeMap {
[name: string]: number
}
const friendsAges: AgeMap = {
"Sandy": 34,
"Joe": 28,
"Sarah": 30,
"Michelle": "fifty", // ERROR! Type 'string' is not assignable to type 'number'.
};
在此,接口将AgeMap
键强制为字符串,将值强制为数字。关键字name
可以是任何标识符,应用于建议您的接口/类型的语法。
您可以使用类似的语法来强制对象为联合类型中的每个条目都具有一个键:
type DayOfTheWeek = "sunday" | "monday" | "tuesday" | "wednesday" | "thursday" | "friday" | "saturday";
type ChoresMap = { [day in DayOfTheWeek]: string };
const chores: ChoresMap = { // ERROR! Property 'saturday' is missing in type '...'
"sunday": "do the dishes",
"monday": "walk the dog",
"tuesday": "water the plants",
"wednesday": "take out the trash",
"thursday": "clean your room",
"friday": "mow the lawn",
};
当然,您也可以使它成为通用类型!
type DayOfTheWeek = "sunday" | "monday" | "tuesday" | "wednesday" | "thursday" | "friday" | "saturday";
type DayOfTheWeekMap<T> = { [day in DayOfTheWeek]: T };
const chores: DayOfTheWeekMap<string> = {
"sunday": "do the dishes",
"monday": "walk the dog",
"tuesday": "water the plants",
"wednesday": "take out the trash",
"thursday": "clean your room",
"friday": "mow the lawn",
"saturday": "relax",
};
const workDays: DayOfTheWeekMap<boolean> = {
"sunday": false,
"monday": true,
"tuesday": true,
"wednesday": true,
"thursday": true,
"friday": true,
"saturday": false,
};
2018年10月10日更新:在下面查看@dracstaxi的答案-现在有一个内置类型Record
可以为您完成大部分任务。
1.2.2020更新: 我已经从答案中完全删除了预制的映射界面。@dracstaxi的答案使它们完全无关。如果您仍要使用它们,请检查编辑历史记录。
x = {}; x[1] = 2;
在Chrome中运行,然后Object.keys(x)
返回[“ 1”]并JSON.stringify(x)
返回'{“ 1”:2}'。typeof Number
(例如,Infinity,NaN,1e300、999999999999999999999等)的极端情况将转换为字符串键。另外注意的其它角落的情况下为字符串键一样x[''] = 'empty string';
,x['000'] = 'threezeros';
x[undefined] = 'foo'
。
快速更新:自Typescript 2.1起,有一个内置类型Record<T, K>
,其作用类似于字典。
来自docs的示例:
// For every properties K of type T, transform it to U
function mapObject<K extends string, T, U>(obj: Record<K, T>, f: (x: T) => U): Record<K, U>
const names = { foo: "hello", bar: "world", baz: "bye" };
const lengths = mapObject(names, s => s.length); // { foo: number, bar: number, baz: number }
关于TypeScript 2.1文档 Record<T, K>
唯一的缺点我看到使用这种过度{[key: T]: K}
的是,你可以在编码排序关键字是什么您使用的是地方的“钥匙”有用的信息例如,如果你的对象只有黄金键,你可以在那像这样的提示:{[prime: number]: yourType}
。
这是我编写的正则表达式,旨在帮助实现这些转换。这只会转换标签为“键”的情况。要转换其他标签,只需更改第一个捕获组:
找: \{\s*\[(key)\s*(+\s*:\s*(\w+)\s*\]\s*:\s*([^\}]+?)\s*;?\s*\}
更换: Record<$2, $3>
{}
吗?
Record
s中也起作用: const isBroken: Record<"hat" | "teapot" | "cup", boolean> = { hat: false, cup: false, teapot: true };
@Ryan Cavanaugh的回答完全可以,而且仍然有效。值得一提的是,从16秋季开始,我们可以说大多数平台都支持ES6,因此只要需要将某些数据与某些键相关联,几乎总是最好坚持使用Map。
在撰写本文时,let a: { [s: string]: string; }
我们需要记住,在编译完打字稿后就没有像类型数据这样的东西,它仅用于编译。和{[s:string]:string; }将仅编译为{}。
就是说,即使您将编写如下内容:
class TrickyKey {}
let dict: {[key:TrickyKey]: string} = {}
这只是不会编译(即使对于target es6
,您也会error TS1023: An index signature parameter type must be 'string' or 'number'.
因此,实际上您受到字符串或数字作为潜在密钥的限制,因此这里没有太多强制执行类型检查的感觉,尤其要记住,当js尝试通过数字访问密钥时,它将其转换为字符串。
因此,可以肯定的是,即使键是字符串,最佳实践也是使用Map,因此我坚持:
let staff: Map<string, string> = new Map();
let dict: {[key in TrickyKey]: string} = {}
- TrickyKey
字符串文字类型(例如"Foo" | "Bar"
)在哪里。
Map
对象总是更好的想法。映射会带来额外的内存开销,并且(更重要的是)需要从存储为JSON字符串的任何数据中手动实例化映射。它们通常非常有用,但并不是纯粹出于从中获取类型的目的。