在C#中,可以使用StringComparer
创建不区分大小写的字典(对于字符串类型的键):
Dictionary<string, int> dict = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
我正在寻找TypeScript中的相同功能,但是在网上搜索时,看起来好像它尚未内置在TypeScript中。
作为一种解决方法,我目前在代码中的任何地方使用toLowerCase()
,向字典添加值或从字典中读取值。但是,这样容易出错,我正在寻找更好的解决方案。
示例: 添加值后
dict = {};
dict['keystring'] = 1;
我希望能够使用dict['keystring]
或dict['KEYSTRING']
来访问它,而不必担心正确的大小写。建议使用TypeScript解决此问题的方法是什么?
答案 0 :(得分:2)
在运行时,您可以非常接近使用Proxy
的要求。
TypeScript在强行键入string
之后的键方面无济于事,因为类型系统无法表示对string literal types的字符串操作的影响。因此,如果您希望使用keystring
作为已知键的对象,则编译器将不知道KEYSTRING
也是已知键。对于处理字符串文字类型(例如using regular expressions on them),有一些建议,但是目前该语言中没有任何内容。幸运的是,我想您要的是字典类型,这通常意味着键只是string
。只要您不希望编译器为您跟踪有效的密钥,就可以了。
这是使用Proxy
的可能实现。请注意,我还没有完全测试所有可能的边缘情况,但是基本思想是使所有接受属性键的事物都成为障碍,并将其替换为规范版本:
function dictWithCanonicalKeys<V>(canon: (prop: keyof any) => keyof any) {
return new Proxy<{ [k: string]: V }>(
{},
{
get(target, prop) {
return Reflect.get(target, canon(prop));
},
set(target, prop, value) {
return Reflect.set(target, canon(prop), value);
},
has(target, prop) {
return Reflect.has(target, canon(prop));
},
defineProperty(target, prop, attribs) {
return Reflect.defineProperty(target, canon(prop), attribs);
},
deleteProperty(target, prop) {
return Reflect.deleteProperty(target, canon(prop));
},
getOwnPropertyDescriptor(target, prop) {
return Reflect.getOwnPropertyDescriptor(target, canon(prop));
}
}
);
}
让我们使用它,传入一个规范化函数,该函数将密钥转换为小写字母(如果它是string
,即...它只剩下symbol
个密钥):
const dict = dictWithCanonicalKeys<number | undefined>(
p => (typeof p === "string" ? p.toLowerCase() : p)
);
dict.keyString = 1;
console.log(dict.KEYSTRING); // 1
dict.KEYstring = "two"; // error! "two" is not a number
dict.KEYstring = 2;
console.log(dict.keyStrinG); // 2
console.log(JSON.stringify(dict)); // {"keystring": 2};
console.log("KeyString" in dict); // true
Object.keys(dict).forEach(k => console.log(k + ":" + dict[k])); // keystring:2
在我看来,这一切都很合理。
最后,请注意:您应该小心地在代码中引入类似的内容。对于大多数开发人员来说,发现他们所谓的普通对象具有不区分大小写的键(console.log(Object.keys(dict).indexOf("keyString")); // -1?!
)实在令人惊讶,即使您可以向开发人员解释它,其IDE也无法理解,并且可能会标记一个与众不同的键如果来自预期的错误(例如KeyString
)是错误的。如果您这样做是为了处理用户输入,则可以在允许输入程序的地方定义严格的障碍,然后规范该情况,这样可能会更干净一些,因此该词典可能很不为人所知,并且可以将其实现为普通对象。
当然,只有您知道用例,不区分大小写的类字典对象才是正确的选择。如果是这样,希望以上代码对您有所帮助。祝你好运!
答案 1 :(得分:0)
这是不可能的。无论如何,具有动态添加属性的普通JS对象并不是真正的通用字典。 JS中的等效项是Map,但密钥也does not support replacing the comparison operator。
您的方法可能是最好的选择。您可以通过将存储空间(您的普通JS对象或Map
)包装在包装对象中来对其进行形式化,以确保使用键的所有操作在进行比较或查找之前都将它们变为小写。