How to rewrite code to avoid TSLint "object access via string literals"

TypescriptTslint

Typescript Problem Overview


I'm pretty new to TypeScript and I would like to know if there exists a good way to rewrite code to avoid TSLint error "object access via string literals is disallowed" in the following code

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: At the end the content above will be part of a self-generated file with more than 300 ECStructs, so I would like to have the class definition (e.g. ECStruct1) followed by its meta-description (e.g. fields['ECStruct1']).

Typescript Solutions


Solution 1 - Typescript

You have a couple options here:

1) Just disable the rule

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

2) Use a variable instead of a string literal

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

3) Write/Generate an explicit interface

See MartylX's answer above. Essentially:

interface ECFieldList {
    ECStruct1: ECType[];
}

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

Any of these are reasonable solutions, although I'm not as much of a fan of #2 because it's mangling up your code for no good reason. If you're generating code anyways, perhaps generating a type for fields as in #3 is a good solution.

Solution 2 - Typescript

You can get rid of the rule. Look for tslint.json, the add a property "no-string-literal" with false, in rules::

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

Solution 3 - Typescript

Just use template literal annotation.

fields[`ECStruct1`]

Solution 4 - Typescript

What about this way? I don't know if you need the indexer ([structName: string]: Array<ECType>;) or not.

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

Solution 5 - Typescript

Probably not the best option, but using

fields['ECStruct1'.toString()]

works too

Solution 6 - Typescript

A simple way is to define a variable to hold the value of ECStruct1:

const sampleName = 'ECStruct1';

and then, get access to the object by using the variable as index:

fields[sampleName] ...

Solution 7 - Typescript

I have faced the same error. but i tried to make use of the type of Headers of Request object and it worked for me. Below is how I managed to resolve the issue.

const objToAdd: { [key: string]: string } = {};
objToAdd.type = 'typeToAdd';
objToAdd.key = 'keyToAdd';
objToAdd.value = 'valueToAdd';

if you see the type { [key: string]: string } tells the TSLint that this object takes keys and values of type string. Similarly, { [key: string]: any } types specifies that the keys are of string type and values of are of any type

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDenis CappellinView Question on Stackoverflow
Solution 1 - TypescriptJKillianView Answer on Stackoverflow
Solution 2 - TypescriptsuhailvsView Answer on Stackoverflow
Solution 3 - Typescriptnyc_coderView Answer on Stackoverflow
Solution 4 - TypescriptMartyIXView Answer on Stackoverflow
Solution 5 - TypescriptPergolaView Answer on Stackoverflow
Solution 6 - TypescriptAli TouraniView Answer on Stackoverflow
Solution 7 - TypescriptAbhilashView Answer on Stackoverflow