TSLint「文字列リテラルを介したオブジェクトアクセス」を回避するためにコードを書き直す方法


85

私は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' }
];

更新:最後に、上記のコンテンツは300ECStruct秒を超える自己生成ファイルの一部になるため、クラス定義(eg ECStruct1)の後にメタ記述(eg fields['ECStruct1'])を付けたいと思います。


4
I TSを使ったことがないが、エラーを見て、コードを見て、私はあなたが交換する必要があると言うだろうfields['ECStruct1']fields.ECStruct1。オブジェクトの小道具にアクセスするためにドット表記を使用することは、通常、文字列リテラルアクセスよりも優先されます。
ジェイミーディクソン

1
ありがとう。すでに試しましたfields.ECStruct1=が、TSコンパイラでは許可されていません:エラーTS2339プロパティ 'ECStruct1'はタイプ '{[structName:string]:ECType [];に存在しません。} '。
デニスカペリン2015年

回答:


152

ここにはいくつかのオプションがあります。

ルールを無効にするだけです

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

文字列リテラルの代わりに変数を使用する

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

明示的なインターフェースの書き込み/生成

上記のMartylXの回答を参照してください。基本的に:

interface ECFieldList {
    ECStruct1: ECType[];
}

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

これらはどれも合理的な解決策ですが、正当な理由もなくコードを混乱させているため、私は#2のファンではありません。とにかくコードを生成している場合は、おそらくfields#3のように型を生成するのが良い解決策です。


48

あなたはルールを取り除くことができます。を探し、::にtslint.jsonプロパティ"no-string-literal"を追加します。falserules

{
"rules": {
    "no-string-literal": false,
    ... other rules ...

41

テンプレートリテラル注釈を使用するだけです。

fields[`ECStruct1`]

4
それは非常に警告の目的を打ち負かすので醜いトリック。しかし、それは私の問題を簡単な方法で解決します。
ロスマノス

構成によっては、これにより新しい警告が作成される場合があります。 `should be '(quotemark)tslint(1)
ruble

6

この方法はどうですか?インデクサー([structName: string]: Array<ECType>;)が必要かどうかはわかりません。

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

質問を編集して詳細を追加したので、このコメントは明確になっているはずです。私が持っ避けたいinterfaceNの定義をECStructして、export var fields...私はすべての実際の定義を書くところECStruct
デニスカペリン2015年

tslintの設定は何ですか?有効になっていると思いますno-string-literal(文字列リテラルを介したオブジェクトアクセスを禁止します。- npmjs.com/ package / tslint
Martin Vseticka 2015年

1
はい、オプションがno-string-literalグローバルに有効になり、上記のコードを含むファイルでのみコメント付きで無効にしました/* tslint:disable: no-string-literal */
デニスカペリン2015年

さて、変数(すなわちfields[variable])で括弧構文を使用し、 文字列(すなわちfields.ECStruct1)でドット構文を使用すれば、大丈夫です。
Martin Vseticka 2015年

5

おそらく最良の選択肢ではありませんが、

fields['ECStruct1'.toString()]

も動作します


2
これをしないでください。リンターが存在するのは、プロジェクトを設定した人が、リンターのルールをハックするのではなく、ベストコードプラクティスに従うことを望んでいるからです。
アンディ

0

簡単な方法は、ECStruct1の値を保持する変数を定義することです。

const sampleName = 'ECStruct1';

次に、変数をインデックスとして使用して、オブジェクトにアクセスします。

fields[sampleName] ...
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.