Cómo reescribir el código para evitar TSLint "acceso a objetos a través de cadenas literales"

82

Soy bastante nuevo en TypeScript y me gustaría saber si existe una buena manera de reescribir el código para evitar el error TSLint "el acceso al objeto a través de cadenas literales no está permitido" en el siguiente código

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

Actualización : Al final, el contenido anterior será parte de un archivo autogenerado con más de 300 ECStructs, por lo que me gustaría tener la definición de la clase (por ejemplo ECStruct1) seguida de su metadescripción (por ejemplo fields['ECStruct1']).

Denis Cappellin
fuente
4
Nunca he usado TS, pero al ver el error y el código, diría que necesita reemplazarlo fields['ECStruct1']por fields.ECStruct1. Por lo general, se prefiere el uso de la notación de puntos para acceder a los accesorios de los objetos al acceso literal de cadena.
Jamie Dixon
1
Gracias. Ya lo probé, pero fields.ECStruct1=el compilador TS no lo permite: Error TS2339 La propiedad 'ECStruct1' no existe en el tipo '{[structName: string]: ECType []; } '.
Denis Cappellin

Respuestas:

148

Tienes un par de opciones aquí:

Solo deshabilita la regla

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

Usa una variable en lugar de una cadena literal

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

Escribir / generar una interfaz explícita

Vea la respuesta de MartylX arriba . Esencialmente:

interface ECFieldList {
    ECStruct1: ECType[];
}

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

Cualquiera de estas son soluciones razonables, aunque no soy tan fan del # 2 porque está alterando tu código sin una buena razón. Si está generando código de todos modos, quizás generar un tipo fieldscomo en el n. ° 3 sea una buena solución.

JKillian
fuente
48

Puedes deshacerte de la regla. Busque tslint.json, el agregar una propiedad "no-string-literal"con false, en rules:

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

Simplemente use la anotación literal de plantilla.

fields[`ECStruct1`]
nyc_coder
fuente
2
agradable y simple. ¡Gracias!
brando
4
Truco feo ya que frustra el propósito de la misma advertencia. pero resuelve mi problema de una manera sencilla.
LosManos
1
truco de un año!
Kacpers
6

¿Y de esta manera? No sé si necesita el indexador ( [structName: string]: Array<ECType>;) o no.

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'}
    ]
};
Martín Vseticka
fuente
Edité mis preguntas y agregué más detalles, por lo que este comentario debería ser claro. Me gustaría evitar tener las definiciones interfacecon N de ECStructy luego export var fields...dónde escribo la definición real de cada ECStruct.
Denis Cappellin
¿Cuál es su configuración para tslint? Supongo que ha habilitado no-string-literal(no permite el acceso a objetos a través de literales de cadena. - npmjs.com/package/tslint )
Martin Vseticka
1
Sí, ahora tengo la opción no-string-literalhabilitada globalmente y solo en el archivo con el código anterior la deshabilité con comentario /* tslint:disable: no-string-literal */.
Denis Cappellin
Bueno, use la sintaxis de corchetes con variables (es decir fields[variable]) y la sintaxis de puntos con cadenas (es decir fields.ECStruct1) y debería estar bien.
Martin Vseticka
5

Probablemente no sea la mejor opción, pero usar

fields['ECStruct1'.toString()]

funciona tambien

Pérgola
fuente
Rapido y Facil.
Dani
1
Por favor no hagas esto. El linter está ahí porque la persona que configuró el proyecto quiere que sigas las mejores prácticas de código, no hackear las reglas del linter.
Andy
0

Una forma sencilla es definir una variable para contener el valor de ECStruct1:

const sampleName = 'ECStruct1';

y luego, obtenga acceso al objeto usando la variable como índice:

fields[sampleName] ...
Alex Trn
fuente