在TypeScript中强制分配?

时间:2017-01-13 23:28:27

标签: typescript

例如,我想要一个带有数字对象的函数,并用字符串化的值替换每个数字。在JavaScript中我可以写这样的东西:

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实现只能在选项上转换此字段将对象转换为UTCString,然后只取整个选项对象,解析它并附加到cookie字符串。

选项对象除了一个字段是可以使用的,因此为了满足TypeScript的要求而为它分配另一个变量似乎有点烦人。

看起来有三种方法,但每种方法都有其自身的局限性:

  1. “肮脏的黑客”风格。
  2. 第一种方法是使用类型转换:

    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
       }
    }
    

    首先,这个问题迫使我们使用类型转换两次(同时将属性设置为格式化的值并解析选项对象),其次,它违反了类型安全的原则,它破坏了使用的所有好处打字稿。

    1. “好的我会处理这种风格。
    2. 我们可以接受格式化的字符串作为“expires”参数的可能值。但这意味着我们还必须改变实施。

      type ExtendedCookieOptions = {
        domain?: string, 
        path? : string,
        expires?: string | Date
      };
      
      function setCookie(name : string, value : string, options : ExtendedCookieOptions) {...}
      
      1. “好的,我们分配一个变量并使用它”Lodewijk描述的样式。

        function setCookie(name:string,value:string,options:cookieOptions){   让params:{[index:string]:string} = options as any; //之后,我们忘记了“options”变量并改为使用“params” }

      2. 同样,在这里我们必须执行一个在JavaScript中看起来绝对无用的操作,只是为了满足TypeScript的要求,并且s why I didn想要添加变量,但在这种情况下它似乎是最好的出路。

3 个答案:

答案 0 :(得分:0)

您可以在作业中执行演员表:

function myStringifier(object: { [index: string]: number}): void {
  for (let key in object) {
    object[key] = object[key].toString() as any; // Cast to any here.
  }
}

这不需要任何其他变量。

答案 1 :(得分:0)

您可以使用类型[index: string]: number | string(如之前路易斯建议的那样),但这也意味着您可以在对象中混合使用数字和类型,而您可能希望在不混合的情况下使用其中一种或另一种。

以下是如何在不分配其他变量的情况下实现额外的类型安全性。

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;
}

要清楚result不是&#34;已分配&#34;的附加变量,因为result将在堆栈上结束,这是预先分配的内存。

答案 2 :(得分:0)

  

P.S。:将对象参数的类型设置为:

     

{[index:string]:number |串}    - 也不是出路。我想确保传递的参数是一个数字对象。

如果您立即将同一个对象变为字符串对象,那么您传入的对象不是数字对象。它是数字或字符串的对象。这是强制您的对象具有数字键的错误位置 - 您最初创建对象时应该这样做。

对于它的价值,我输入变量的方式如下:{ [index: string]: number } | { [index: string]: string }。现在您知道所有number s或全部string s。