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 ECStruct
sekundami, więc chciałbym, aby definicja klasy (np. ECStruct1
), A następnie jej meta-opis (np fields['ECStruct1']
.).
typescript
tslint
Denis Cappellin
źródło
źródło
fields['ECStruct1']
zfields.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.fields.ECStruct1=
kompilator TS na to nie zezwala: Błąd TS2339 Właściwość „ECStruct1” nie istnieje w typie „{[structName: string]: ECType []; } '.Odpowiedzi:
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
fields
jak w punkcie 3 jest dobrym rozwiązaniem.źródło
Możesz pozbyć się reguły. Poszukaj
tslint.json
, dodaj właściwość"no-string-literal"
zfalse
, wrules
:{ "rules": { "no-string-literal": false, ... other rules ...
źródło
Po prostu użyj adnotacji literału szablonu.
fields[`ECStruct1`]
źródło
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'} ] };
źródło
interface
z N,ECStruct
a następnie miejsca, wexport var fields...
którym piszę rzeczywistą definicję każdegoECStruct
.no-string-literal
(nie zezwala na dostęp do obiektów za pośrednictwem literałów ciągów. - npmjs.com/package/tslint )no-string-literal
włączoną globalnie i dopiero w pliku z powyższym kodem wyłączyłem ją komentarzem/* tslint:disable: no-string-literal */
.fields[variable]
) I składni kropek z łańcuchami (tj.fields.ECStruct1
) I powinno być dobrze.Prawdopodobnie nie najlepsza opcja, ale używanie
fields['ECStruct1'.toString()]
działa też
źródło
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:
źródło