Jak przepisać kod, aby uniknąć TSLint „dostępu do obiektów za pośrednictwem literałów tekstowych”

85

Jestem całkiem nowy w TypeScript i chciałbym wiedzieć, czy istnieje dobry sposób na przepisanie kodu w celu uniknięcia błędu TSLint „dostęp do obiektu za pośrednictwem literałów ciągu jest niedozwolony” w poniższym kodzie

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

Aktualizacja : Na końcu powyższa zawartość będzie częścią samodzielnie wygenerowanego pliku z ponad 300 ECStructsekundami, więc chciałbym, aby definicja klasy (np. ECStruct1), A następnie jej meta-opis (np fields['ECStruct1'].).

Denis Cappellin
źródło
4
Nigdy nie używany TS ale patrząc na błędy i patrząc na kod, powiedziałbym, trzeba wymienić fields['ECStruct1']z fields.ECStruct1. Używanie notacji z kropką do uzyskiwania dostępu do właściwości obiektów jest zwykle preferowane zamiast dostępu do literału łańcuchowego.
Jamie Dixon
1
Dzięki. Próbowałem już tego, ale fields.ECStruct1=kompilator TS na to nie zezwala: Błąd TS2339 Właściwość „ECStruct1” nie istnieje w typie „{[structName: string]: ECType []; } '.
Denis Cappellin

Odpowiedzi:

152

Masz tutaj kilka opcji:

Po prostu wyłącz regułę

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

Użyj zmiennej zamiast literału ciągu

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

Napisz / wygeneruj jawny interfejs

Zobacz odpowiedź MartylX powyżej . Głównie:

interface ECFieldList {
    ECStruct1: ECType[];
}

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

Każde z tych rozwiązań jest rozsądnymi rozwiązaniami, chociaż nie jestem aż tak wielkim fanem # 2, ponieważ zniekształca twój kod bez powodu. Jeśli mimo wszystko generujesz kod, być może generowanie typu dla fieldsjak w punkcie 3 jest dobrym rozwiązaniem.

JKillian
źródło
49

Możesz pozbyć się reguły. Poszukaj tslint.json, dodaj właściwość "no-string-literal"z false, w rules:

{
"rules": {
    "no-string-literal": false,
    ... other rules ...
suhailvs
źródło
42

Po prostu użyj adnotacji literału szablonu.

fields[`ECStruct1`]
nyc_coder
źródło
4
Brzydka sztuczka, ponieważ pokonuje cel samego ostrzeżenia. ale to rozwiązuje mój problem w prosty sposób.
LosManos
w zależności od konfiguracji może to spowodować powstanie nowego ostrzeżenia: `powinno być '(znak cudzysłowu) tslint (1)
rubel
6

A co w ten sposób? Nie wiem, czy potrzebujesz indeksatora ( [structName: string]: Array<ECType>;), czy nie.

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
źródło
Zredagowałem swoje pytania i dodałem więcej szczegółów, więc ten komentarz powinien być jasny. Chciałbym uniknąć posiadania definicji interfacez N,ECStruct a następnie miejsca, w export var fields...którym piszę rzeczywistą definicję każdego ECStruct.
Denis Cappellin
Jakie są twoje ustawienia dla tslint? Domyślam się, że masz włączone no-string-literal(nie zezwala na dostęp do obiektów za pośrednictwem literałów ciągów. - npmjs.com/package/tslint )
Martin Vseticka
1
Tak, teraz mam opcję no-string-literalwłączoną globalnie i dopiero w pliku z powyższym kodem wyłączyłem ją komentarzem /* tslint:disable: no-string-literal */.
Denis Cappellin
Cóż, użyj składni nawiasów ze zmiennymi (tj. fields[variable]) I składni kropek z łańcuchami (tj. fields.ECStruct1) I powinno być dobrze.
Martin Vseticka
5

Prawdopodobnie nie najlepsza opcja, ale używanie

fields['ECStruct1'.toString()]

działa też

Pergola
źródło
2
Proszę nie rób tego. Linter istnieje, ponieważ osoba, która skonfigurowała projekt, chce, abyś przestrzegał najlepszych praktyk kodowania, a nie hakowania reguł lintera.
Andy,
0

Prostym sposobem jest zdefiniowanie zmiennej przechowującej wartość ECStruct1:

const sampleName = 'ECStruct1';

a następnie uzyskaj dostęp do obiektu, używając zmiennej jako indeksu:

fields[sampleName] ...
Alex Trn
źródło