So schreiben Sie Code neu, um TSLint-Objektzugriff über Zeichenfolgenliterale zu vermeiden

82

Ich bin ziemlich neu in TypeScript und möchte wissen, ob es eine gute Möglichkeit gibt, Code neu zu schreiben, um den TSLint-Fehler "Objektzugriff über Zeichenfolgenliterale ist nicht zulässig" im folgenden Code zu vermeiden

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

Update : Am Ende wird der obige Inhalt Teil einer selbst generierten Datei mit mehr als 300 ECStructs sein, daher möchte ich die Klassendefinition (z. B. ECStruct1) gefolgt von ihrer Meta-Beschreibung (z fields['ECStruct1']. B. ).

Denis Cappellin
quelle
4
Ich habe noch nie TS verwendet , aber bei dem Fehler suchen und Blick auf den Code, ich würde sagen , dass Sie ersetzen fields['ECStruct1']mit fields.ECStruct1. Die Verwendung der Punktnotation für den Zugriff auf Objekt-Requisiten wird normalerweise dem Zugriff auf String-Literale vorgezogen.
Jamie Dixon
1
Vielen Dank. Ich habe es bereits versucht, fields.ECStruct1=ist aber vom TS-Compiler nicht zulässig: Fehler TS2339-Eigenschaft 'ECStruct1' existiert nicht für Typ '{[structName: string]: ECType []; } '.
Denis Cappellin

Antworten:

148

Sie haben hier einige Möglichkeiten:

Deaktivieren Sie einfach die Regel

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

Verwenden Sie eine Variable anstelle eines Zeichenfolgenliteral

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

Schreiben / Generieren einer expliziten Schnittstelle

Siehe MartylXs Antwort oben . Im Wesentlichen:

interface ECFieldList {
    ECStruct1: ECType[];
}

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

All dies sind vernünftige Lösungen, obwohl ich nicht so ein Fan von # 2 bin, weil es Ihren Code ohne guten Grund durcheinander bringt. Wenn Sie sowieso Code generieren, ist es möglicherweise fieldseine gute Lösung, einen Typ für wie in # 3 zu generieren .

JKillian
quelle
48

Sie können die Regel loswerden. Suchen Sie nach tslint.jsondem Hinzufügen einer Eigenschaft "no-string-literal"mit false, in rules::

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

Verwenden Sie einfach die wörtliche Annotation der Vorlage.

fields[`ECStruct1`]
nyc_coder
quelle
2
schön und einfach. Danke!
Brando
4
Hässlicher Trick, da er den Zweck der Warnung zunichte macht. aber es löst mein Problem auf einfache Weise.
LosManos
1
Hack eines Jahres!
Kacpers
6

Was ist mit diesem Weg? Ich weiß nicht, ob Sie den Indexer ( [structName: string]: Array<ECType>;) benötigen oder nicht.

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'}
    ]
};
Martin Vseticka
quelle
Ich habe meine Fragen bearbeitet und weitere Details hinzugefügt, daher sollte dieser Kommentar klar sein. Ich möchte vermeiden, die interfacemit N Definitionen von ECStructund dann die, export var fields...wo ich die tatsächliche Definition von jedem schreibe ECStruct.
Denis Cappellin
Was sind Ihre Einstellungen für tslint? Ich denke, Sie haben aktiviert no-string-literal(verhindert den Objektzugriff über String-Literale. - npmjs.com/package/tslint )
Martin Vseticka
1
Ja, jetzt habe ich die Option no-string-literalglobal aktiviert und nur in der Datei mit dem obigen Code habe ich sie mit Kommentar deaktiviert /* tslint:disable: no-string-literal */.
Denis Cappellin
Verwenden Sie die Klammernsyntax mit Variablen (dh fields[variable]) und die Punktsyntax mit Zeichenfolgen (dh fields.ECStruct1), und Sie sollten in Ordnung sein.
Martin Vseticka
5

Wahrscheinlich nicht die beste Option, aber mit

fields['ECStruct1'.toString()]

funktioniert auch

Pergola
quelle
schnell und einfach.
Dani
1
Bitte mach das nicht. Der Linter ist da, weil die Person, die das Projekt eingerichtet hat, möchte, dass Sie die besten Code-Praktiken befolgen und nicht die Linter-Regeln umgehen.
Andy
0

Eine einfache Möglichkeit besteht darin, eine Variable zu definieren, die den Wert von ECStruct1 enthält:

const sampleName = 'ECStruct1';

und erhalten Sie dann Zugriff auf das Objekt, indem Sie die Variable als Index verwenden:

fields[sampleName] ...
Alex Trn
quelle