我想在Typescript对象中存储string ->字符串的映射,并强制所有值映射到字符串。例如:
var stuff = {};
stuff["a"] = "foo"; // okay
stuff["b"] = "bar"; // okay
stuff["c"] = false; // ERROR! bool != string
是否有一种方法让我强制值必须是字符串(或任何类型..)?
我想在Typescript对象中存储string ->字符串的映射,并强制所有值映射到字符串。例如:
var stuff = {};
stuff["a"] = "foo"; // okay
stuff["b"] = "bar"; // okay
stuff["c"] = false; // ERROR! bool != string
是否有一种方法让我强制值必须是字符串(或任何类型..)?
当前回答
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
其他回答
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
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强制键为字符串,值为数字。关键字名称可以是任何标识符,应该用于建议接口/类型的语法。
你可以使用类似的语法来强制一个对象对union类型中的每个条目都有一个键:
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,
};
10.10.2018更新: 看看下面@dracstaxi的答案——现在有一个内置的类型Record,它可以帮你完成大部分工作。
1.2.2020更新: 我已经完全从我的回答中删除了预先制作的映射接口。@dracstaxi的回答让他们完全无关紧要。如果您仍然想使用它们,请检查编辑历史记录。
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!');
@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