Typescript 为映射对象指定动态变量的类型脚本
我正在处理这个问题(从) 给定一个短语,计算该短语中每个单词的出现次数 例如输入“olly-olly-in-come-free” 我很确定我已经在理论上找到了答案,但是我在类型方面遇到了麻烦。拆分字符串后,我运行一个reduce函数,返回一个Typescript 为映射对象指定动态变量的类型脚本,typescript,Typescript,我正在处理这个问题(从) 给定一个短语,计算该短语中每个单词的出现次数 例如输入“olly-olly-in-come-free” 我很确定我已经在理论上找到了答案,但是我在类型方面遇到了麻烦。拆分字符串后,我运行一个reduce函数,返回一个Map,如下所示: return string.split(' ').reduce((acc: Map<string, number>, word): Map<string, number> => { if
Map
,如下所示:
return string.split(' ').reduce((acc: Map<string, number>, word): Map<string, number> => {
if (acc.has(word)) {
console.log("working")
// I've tried this
return acc[word] + 1
// And this
return acc.set(word, acc.get(word) + 1)
} else {
return acc.set(word, 1)
}
}, new Map<string, number>())
returnstring.split(“”).reduce((acc:Map,word):Map=>{
如果(附件有(文字)){
控制台日志(“工作”)
//我试过这个
返回acc[word]+1
//还有这个
返回acc.set(word,acc.get(word)+1)
}否则{
返回附件集(字,1)
}
},新映射())
我在调整这个过程中遇到的几个问题是
1) acc
没有“has”方法(当我键入acc
asany
而不是Map时)
2) acc.get(word)
可能未定义,因此不起作用(我检查了它,但Typescript没有看到?)
当然,无论如何,我都有可能做错事,但是有没有办法让我所做的工作正常呢?A
Map
在JavaScript中,因此TypeScript不会将其键/值对作为属性直接存储在对象上,所以acc[word]
除非将映射
替换为类似{[k:string]:number | undefined}
的字典对象类型,否则表示法将不起作用。这是一个不错的方法,但出于某种原因,您可能希望使用贴图而不是普通对象,因此我们将继续使用它
TypeScript不理解Map
实例的有(x)
方法返回true
意味着对get(x)
的后续调用将不会未定义。甚至没有好的方法来表示这样的约束。您可以扩充,使has(x)
方法充当映射
实例或x
参数的函数,这可能会根据您所做的工作进行排序,但它非常复杂且非常脆弱
如果我想让您的返回acc.set(word,acc.get(word)+1)
行保持JavaScript中的状态,我建议在acc.get(word)
的结果上使用。在这里,您知道检查acc.has(word)
意味着acc.get(word)
将是一个数字
,而不是数字|未定义
,但编译器不知道这一点。当你确信编译器不知道的东西时,使用。下面是它的外观:
if (acc.has(word)) {
return acc.set(word, acc.get(word)! + 1); // no error now
}
那太好了。全部完成
然而,类型断言只能隐藏潜在的错误。。。通常,最好使用编译器能够实际验证为类型安全的代码,而不是我们必须断言为安全的代码。那么,我们能做些什么让编译器来帮助我们,而不是反过来呢
我们使用acc.has(word)
来缩小acc.get(word)
的结果。但是如果我们只保存acc.get(word)
的结果并直接检查它会怎么样?然后我们可以完全忘记has()
方法。比如:
const cnt = acc.get(word);
if (typeof cnt !== 'undefined') {
return acc.set(word, cnt + 1); // no error here
} else {
return acc.set(word, 1);
}
我们已经明确检查了cnt
是否为未定义的,正常人理解cnt
是if
语句的true
子句中的数字
好了,现在我们都结束了
嗯,但是typeof cnt==“undefined”
很冗长;我们只需检查cnt
是否为,它适用于除0
以外的所有number
值。由于我们将未定义的
情况视为计数为0
,因此这样做没有什么坏处:
const cnt = acc.get(word);
if (cnt) {
return acc.set(word, cnt + 1);
} else {
return acc.set(word, 1);
}
等等,一旦我们愿意检查真实性,我们就可以使用来确保cnt
始终是一个数字
:
const cnt = acc.get(word) || 0; // always a number
if (cnt) {
return acc.set(word, cnt + 1);
} else {
return acc.set(word, 1);
}
但是现在我们知道,cnt
的唯一错误值是0
,因此我们可以始终执行cnt+1
:
const cnt = acc.get(word) || 0;
return acc.set(word, cnt + 1);
现在,cnt
只使用了一次,因此不值得将其作为单独的变量:
return acc.set(word, (acc.get(word) || 0) + 1);
哦,一个只包含一个return
语句的箭头函数可以更改为使用以下语句的函数:
函数countStuff(string:string){
返回字符串
.拆分(“”)
.减少(
(acc:Map,word):Map=>
acc.set(word)(acc.get(word)| | 0)+1),
新地图()
);
}
好了,现在我们都结束了!至少我是。希望有帮助。祝你好运 谢谢你那样为我把它分解,它真的很有用!
return acc.set(word, (acc.get(word) || 0) + 1);
function countStuff(string: string) {
return string
.split(" ")
.reduce(
(acc: Map<string, number>, word): Map<string, number> =>
acc.set(word, (acc.get(word) || 0) + 1),
new Map<string, number>()
);
}