在TypeScript中强制赋值?
例如,我想要一个函数,它接受一个数字对象,并用它的字符串化值替换每个数字。在JavaScript中,我可以编写如下内容:在TypeScript中强制赋值?,typescript,Typescript,例如,我想要一个函数,它接受一个数字对象,并用它的字符串化值替换每个数字。在JavaScript中,我可以编写如下内容: function myStringifier(object) { for (let key in object) { object[key] = object[key].toString(); } } myObject = { a: 1, b: 2, c: 3 }; myStringifier(myObject); 但是我如何在TypeScr
function myStringifier(object) {
for (let key in object) {
object[key] = object[key].toString();
}
}
myObject = {
a: 1,
b: 2,
c: 3
};
myStringifier(myObject);
但是我如何在TypeScript中处理这个问题呢?以下代码将产生错误:
function myStringifier(object : {[index: string]: number}) : void {
for (let key in object) {
object[key] = object[key].toString(); /* ERROR! Object properties are of type number
and therefore cannot be assigned any string values to */
}
}
重要提示:我希望这样做,而不在函数范围内分配任何附加变量和/或复制对象或对其的引用
p.S.:将对象参数的类型设置为:
{[index: string]: number | string}
-也不是出路。我想确定传递的参数是一个数字对象
p.p.S.:
谢谢你的回答
我理解需求可能看起来有点关联,所以我可能应该提供真实的案例,而不是抽象的示例
我有一个函数,它接受几个参数,其中一个是附加参数的对象:
function setCookie(name, value, {path, domain, expires}) {...}
参数expires的值类型为Date,因此该函数的JavaScript实现可以将options对象上的这一字段转换为UTCString,然后只需获取整个options对象,解析它并附加到cookie字符串中
除了一个字段可以使用之外,选项对象,因此为它分配另一个变量只是为了满足TypeScript的要求似乎有点烦人
看起来有三条出路,但每一条都有自己的局限性:
type cookieOptions = {
domain?: string,
path? : string,
expires?: Date
};
function setCookie(name : string, value : string, options : cookieOptions) {
if ("expires" in options) {
options.expires = options.expires.toUTCString() as any; // type casting
}
for (let propName in options) {
updatedCookie += `; ${propName}=${options[propName] as any}`; // type casting
}
}
首先,这种担心迫使我们使用类型转换两次(将属性设置为格式化值和解析options对象时),其次,它违反了类型安全原则,这破坏了使用TypeScript的所有好处
type ExtendedCookieOptions = {
domain?: string,
path? : string,
expires?: string | Date
};
function setCookie(name : string, value : string, options : ExtendedCookieOptions) {...}
同样,这里我们必须执行一个在JavaScript中似乎毫无用处的操作,只是为了满足TypeScript的要求,这就是为什么我不想添加变量,但在这种情况下,这似乎是最好的解决方法。您可以在分配中执行强制转换:
function myStringifier(object: { [index: string]: number}): void {
for (let key in object) {
object[key] = object[key].toString() as any; // Cast to any here.
}
}
这不需要任何额外的变量。您可以使用类型
[index:string]:number | string
(正如Louis之前所建议的),但这也意味着您可以在对象中混合数字和类型,而您可能希望不混合其中一个或另一个
function myStringifier(object: {[index: string]: number}): {[index: string]: string} {
let result: {[index: string]: string} = <any> object;
for (let key in object) {
result[key] = object[key].toString();
}
return result;
}
下面是如何在不分配其他变量的情况下实现额外的类型安全性
function myStringifier(object: {[index: string]: number}): {[index: string]: string} {
let result: {[index: string]: string} = <any> object;
for (let key in object) {
result[key] = object[key].toString();
}
return result;
}
函数mystringhier(对象:{[index:string]:number}):{[index:string]:string}{
让结果:{[index:string]:string}=object;
for(让输入对象){
结果[key]=对象[key].toString();
}
返回结果;
}
要清楚的是,result
不是一个“已分配”的附加变量,因为result
将在堆栈上结束,堆栈是预先分配的内存
注意:将对象参数的类型设置为:
{[index: string]: number | string}
{[索引:字符串]:数字|字符串}
-也不是出路。我想确定传递的参数是一个数字对象
如果您立即将同一个对象变为字符串对象,则传递的对象不是数字对象。它是数字或字符串的对象。这是一个错误的地方来强制您的对象具有数字键-您应该在最初创建对象时这样做
值得一提的是,我键入变量的方式如下:
{[index:string]:number}{[index:string]:string}
。现在您知道它要么是allnumber
s,要么是allstring
s 我更喜欢你之前的答案,因为这样你得到一个TypeScript认为有数字但实际上有字符串的对象,这只是另一种打中你自己脚的方式。OP编辑了这个问题,明确拒绝了我最初的解决方案。鉴于OP的要求,必须以使TypeScript类型声明成为谎言的方式修改原始对象。您的解决方案的优点是提供了反映新类型的返回值,但它违背了OP的要求,即不存在其他变量。我想得越多,我就越觉得需求是任意的。我的解决方案没有额外的变量<代码>结果是指向堆栈上对象的指针。虽然在某些js框架中,改变对象而不是生成新对象是一项特殊要求,但该要求听起来确实是任意的。@LodewijkBogaards您的解决方案确实有一个附加变量<代码>结果是一个附加变量。它是否保存在堆栈中并不重要:它仍然是一个变量。不管它是否是指针:它仍然是一个变量。您的上一个要求违反了类型安全:函数返回后,此函数的调用方仍将对象类型为{[index:string]:number}
,这是错误的,因为值实际上是字符串。(没有办法说函数参数的类型在调用函数后发生了变化。)虽然类型可能更具信息性,但这并不比实际上只对对象的项使用number | string
要好多少,因为如果从该函数中取消引用项