【问题标题】:How to rewrite code to avoid TSLint "object access via string literals"如何重写代码以避免 TSLint“通过字符串文字进行对象访问”
【发布时间】:2016-01-27 23:49:27
【问题描述】:

我是 TypeScript 的新手,我想知道是否存在重写代码的好方法,以避免以下代码中出现 TSLint 错误“不允许通过字符串文字访问对象”

interface ECType
{
    name: string;
    type: string;
    elementType?: string;
}

export var fields: { [structName: string]: Array<ECType>; } = { };

class ECStruct1 {
    foo: string;
    bar: number;
    baz: boolean;
    qux: number;
    quux: number;
    corge: ECStruct2[];
    grault: ECStruct2;

    constructor() {
        ...
    }
} 

fields['ECStruct1'] = [
    { name: 'foo', type: 'string' },
    { name: 'bar', type: 'int' },
    { name: 'baz', type: 'bool' },
    { name: 'qux', type: 'long' },
    { name: 'quux', type: 'ulong' },
    { name: 'corge', type: 'array', elementType: 'ECStruct2' },
    { name: 'grault', type: 'ECStruct2' }
];

更新:最后上面的内容将是一个超过300个ECStructs的自生成文件的一部分,所以我想要类定义(例如ECStruct1 ) 后跟其元描述(例如fields['ECStruct1'])。

【问题讨论】:

  • 我从未使用过 TS,但查看错误并查看代码,我会说您需要将 fields['ECStruct1'] 替换为 fields.ECStruct1。使用点符号来访问对象道具通常比字符串文字访问更受欢迎。
  • 谢谢。我已经尝试过了,但是 TS 编译器不允许 fields.ECStruct1=:错误 TS2339 属性 'ECStruct1' 在类型 '{ [structName: string]: ECType[]; 上不存在}'。

标签: typescript tslint


【解决方案1】:

这样怎么样?我不知道你是否需要索引器([structName: string]: Array&lt;ECType&gt;;)。

interface ECType {
    name: string;
    type: string;
    elementType?: string;
}

interface ECFieldList {
    ECStruct1: ECType[];
}

export var fields:ECFieldList = {
    ECStruct1: [
        {name: 'foo', type: 'string'},
        {name: 'bar', type: 'int'},
        {name: 'baz', type: 'bool'},
        {name: 'qux', type: 'long'},
        {name: 'quux', type: 'ulong'},
        {name: 'corge', type: 'array', elementType: 'ECStruct2'},
        {name: 'grault', type: 'ECStruct2'}
    ]
};

【讨论】:

  • 我编辑了我的问题并添加了更多细节,所以这个评论应该很清楚。我想避免使用interfaceECStructN 定义,然后是export var fields...,我在其中编写每个ECStruct 的实际定义。
  • 你对 tslint 的设置是什么?我猜你已经启用了no-string-literal(不允许通过字符串文字访问对象。-npmjs.com/package/tslint
  • 是的,现在我可以全局启用no-string-literal 选项,并且仅在包含上述代码的文件中,我用注释/* tslint:disable: no-string-literal */ 禁用了它。
  • 好吧,对变量使用括号语法(即fields[variable])和对字符串使用点语法(即fields.ECStruct1),你应该没问题。
【解决方案2】:

你有几个选择:

1) 只需禁用规则

/* tslint:disable:no-string-literal */
whatever.codeHere()
/* tslint:enable:no-string-literal */

2) 使用变量而不是字符串文字

// instead of 
fields['ECStruct1'] = ...
// do something like
let key = 'ECStruct1';
fields[key] = ...

3) 编写/生成显式接口

MartylX's answer above。本质上:

interface ECFieldList {
    ECStruct1: ECType[];
}

export var fields:ECFieldList = {
    ECStruct1: [
        ...

这些都是合理的解决方案,尽管我不太喜欢 #2,因为它会无缘无故地破坏您的代码。如果您仍然要生成代码,那么像 #3 中那样为 fields 生成一个类型可能是一个很好的解决方案。

【讨论】:

    【解决方案3】:

    可能不是最好的选择,但使用

    fields['ECStruct1'.toString()]
    

    也可以

    【讨论】:

    • 请不要这样做。 linter 存在是因为设置项目的人希望您遵循最佳代码实践,而不是绕过 linter 规则。
    【解决方案4】:

    你可以摆脱规则。查找tslint.json,在rules::

    中添加属性"no-string-literal"false
    {
    "rules": {
        "no-string-literal": false,
        ... other rules ...
    

    【讨论】:

      【解决方案5】:

      只需使用模板文字注释。

      fields[`ECStruct1`]
      

      【讨论】:

      • 丑陋的把戏,因为它违背了警告的目的。但它以一种简单的方式解决了我的问题。
      • 根据您的配置,这可能会创建一个新警告:` should be ' (quotemark) tslint(1)
      【解决方案6】:

      一个简单的方法是定义一个变量来保存 ECStruct1 的值:

      const sampleName = 'ECStruct1';
      

      然后,通过使用变量作为索引来访问对象:

      fields[sampleName] ...
      

      【讨论】:

        【解决方案7】:

        我也遇到了同样的错误。但是我尝试使用HeadersRequest 对象的type,它对我有用。以下是我设法解决此问题的方法。

        const objToAdd: { [key: string]: string } = {};
        objToAdd.type = 'typeToAdd';
        objToAdd.key = 'keyToAdd';
        objToAdd.value = 'valueToAdd';
        

        如果你看到 { [key: string]: string } 类型告诉 TSLint 这个对象接受字符串类型的键和值。 同样,{ [key: string]: any } 类型指定键是 string 类型,值是 any 类型

        【讨论】:

          猜你喜欢
          • 2020-02-02
          • 2014-06-16
          • 1970-01-01
          • 2018-07-19
          • 1970-01-01
          • 2013-07-03
          • 1970-01-01
          • 1970-01-01
          • 2017-02-17
          相关资源
          最近更新 更多