我想在Typescript对象中存储string ->字符串的映射,并强制所有值映射到字符串。例如:

var stuff = {};
stuff["a"] = "foo";   // okay
stuff["b"] = "bar";   // okay
stuff["c"] = false;   // ERROR!  bool != string

是否有一种方法让我强制值必须是字符串(或任何类型..)?


当前回答

实际上有一个内置的实用程序记录:

    const record: Record<string, string> = {};
    record['a'] = 'b';
    record[1] = 'c'; // leads to typescript error
    record['d'] = 1; // leads to typescript error

其他回答

@Ryan Cavanaugh的回答完全没问题,而且仍然有效。值得补充的是,在16年秋季,当我们可以宣称ES6被大多数平台支持时,当你需要将一些数据与一些键关联时,几乎总是更好地坚持使用Map。

当我们写let a: {[s:字符串]:字符串;}我们需要记住typescript编译后没有类型数据这样的东西,它只用于编译。和{[s:字符串]:字符串;}将编译为{}。

也就是说,即使你写的是:

class TrickyKey  {}

let dict: {[key:TrickyKey]: string} = {}

这只是不会编译(即使对于目标es6,你也会得到错误TS1023:索引签名参数类型必须是'string'或'number'。

实际上,字符串或数字作为潜在的键是有限的,所以这里没有太多强制类型检查的意义,特别是要记住,当js试图通过数字访问key时,它会将其转换为字符串。

因此,假设最佳实践是使用Map,即使键是字符串,这是相当安全的,所以我坚持使用:

let staff: Map<string, string> = new Map();

实际上有一个内置的实用程序记录:

    const record: Record<string, string> = {};
    record['a'] = 'b';
    record[1] = 'c'; // leads to typescript error
    record['d'] = 1; // leads to typescript error

你可以传递一个名字给未知键,然后写你的类型:

type StuffBody = {
  [key: string]: string;
};

现在你可以在你的类型检查中使用它:

let stuff: StuffBody = {};

但对于FlowType,不需要有名称:

type StuffBody = {
  [string]: string,
};
type KeyOf<T> = keyof T;

class SomeClass<T, R> {
  onlyTFieldsAllowed = new Map<KeyOf<T>, R>();
}

class A {
  myField = 'myField';
}

const some = new SomeClass<A, any>();

some.onlyTFieldsAllowed.set('myField', 'WORKS');
some.onlyTFieldsAllowed.set('noneField', 'Not Allowed!');

基于@shabunc的答案,这将允许将键或值(或两者都是)强制为您想强制的任何值。

type IdentifierKeys = 'my.valid.key.1' | 'my.valid.key.2';
type IdentifierValues = 'my.valid.value.1' | 'my.valid.value.2';

let stuff = new Map<IdentifierKeys, IdentifierValues>();

也应该使用enum而不是类型定义。